Bugku | 审计

审计1 | extract变量覆盖

<?php
$flag='xxx';
extract($_GET); 
if(isset($shiyan))
{
$content=trim(file_get_contents($flag));
if($shiyan==$content)
{
echo'flag{xxx}';
}
else
{
echo'Oh.no';
}
}
?>

涉及知识:extract()

extract(array,extract_rules,prefix)
对于数组中的每个元素,键名用于变量名,键值用于变量值。
第二个参数 用于指定当某个变量已经存在,而数组中又有同名元素时,extract() 函数如何对待这样的冲突。
本函数返回成功设置的变量数目。
可选。extract() 函数将检查每个键名是否为合法的变量名,同时也检查和符号表中的变量名是否冲突。

对非法、数字和冲突的键名的处理将根据此参数决定。可以是以下值之一:

extract_rules可能的值:

    EXTR_OVERWRITE - 默认。如果有冲突,则覆盖已有的变量。
    EXTR_SKIP - 如果有冲突,不覆盖已有的变量。(忽略数组中同名的元素) 
    EXTR_PREFIX_SAME - 如果有冲突,在变量名前加上前缀 prefix。自 PHP 4.0.5 起,这也包括了对数字索引的处理。 
prefix可选。请注意 prefix 仅在 extract_type 的值是 EXTR_PREFIX_SAME,EXTR_PREFIX_ALL,EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS 时需要。如果附加了前缀后的结果不是合法的变量名,将不会导入到符号表中。

前缀和数组键名之间会自动加上一个下划线。

e.g.1
 
<?php 
$a = 'Original'; 
$my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse"); 
extract($my_array); 
echo "$a = $a; $b = $b; $c = $c"; 
?> 
$a = Cat;//默认下的覆盖,当变量名冲突时
$b = Dog;
$c = Horse

<?php
extract($_POST);
//相当于$username = $_POST['username'];
//$password = $_POST['password'];
?> 

思路:GET请求 ?flag=&shiyan=,extract()会将$flag和$shiyan的值覆盖了,将变量的值设置为空或者不存在的文件就满足$shiyan == $content。

$flag是一个目录,最终比较的是$shiyan 和 $content 的内容=>payload:http://123.206.87.240:9009/1.php?flag=&shiyan=

参考:

https://www.freebuf.com/column/150731.html

审计二 | strcmp比较字符串

<?php
$flag = "flag{xxxxx}";
if (isset($_GET['a'])) {
if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。
//比较两个字符串(区分大小写)
die('Flag: '.$flag);
else
print 'No';
}
?>

在PHP 5.3版本以上的strcmp()有一个bypass漏洞,strcmp()在比较字符串和数组的时候直接返回0,这样通过把目标变量设置成数组就可以绕过该函数的限制

payload:http://123.206.87.240:9009/6.php?a[]=

审计三 | urldecode 二次编码


<?php
if(eregi("hackerDJ",$_GET[id])) {
echo("

not allowed!
");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "hackerDJ")
{
echo "

Access granted!
";
echo "

flag
";
}
?>


绕过eregi(),字符匹配(不区分大小写),J对应ASCLL:0x4A,在编码%254A,第一次有浏览器解码成%4A,之后再解码函数解码

payload:http://123.206.87.240:9009/10.php?id=hackerD%254A

审计四 | md5()函数

<?php
error_reporting(0);
$flag = 'flag{test}';
if (isset($_GET['username']) and isset($_GET['password'])) {
if ($_GET['username'] == $_GET['password'])
print 'Your password can not be your username.';
else if (md5($_GET['username']) === md5($_GET['password']))
die('Flag: '.$flag);
else
print 'Invalid password';
}
?>


md5不能处理数组。

payload:?username[]=1&password[]=2

审计5 | 数组返回NULL

<?php
$flag = "flag";

if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
echo 'You password must be alphanumeric';
else if (strpos ($_GET['password'], '--') !== FALSE)
die('Flag: ' . $flag);
else
echo 'Invalid password';
}
?>

“[A-Za-z0-9]"
方括号表示字符集,[A-Za-z0-9]匹配大小写字母和数字其中一个字符
"^[A-Za-z0-9]$"
^表示字符串开始,$表示字符串结束 ,这个匹配只有一个大小写字母和数字字符的字符串

“^[A-Za-z0-9]+$"
+号表示重复1到多次,匹配由多个数字大小字母组成的字符串
 ereg()只能处理字符串的,遇到数组做参数返回NULL,判断用的是 === ,要求类型也相同,而NULL跟FALSE类型是不同的
strpos()的参数不能为数组,否则返回NULL,而判断用的是 !== ,所以这里的条件成立,也能得到flag


something about url

https://chromium.googlesource.com/chromium/src/+/master/docs/security/url_display_guidelines/url_display_guidelines.md#Escaping

原文地址:https://www.cnblogs.com/zuoanfengxi/p/13129078.html