BugkuCTF的代码审计

BugkuCTF代码审计

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函数会使传入的数据转换为变量名和变量的值
首先判断shiyan不为NULL
然后file_get_contents把flag整个文件读入一个字符串中
再然后trim() 函数移除字符串两侧的空白字符或其他预定义字符赋给 c o n t e n t 最 后 判 断 content 最后判断 contentshiyan 是否等于 KaTeX parse error: Expected 'EOF', got '&' at position 33: …ayload ?shiyan=&̲flag= 没有对重名情况进行…shiyan = ,flag同理。所以通过if。

strcmp比较字符串

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

分析:
先判断a不为null,再判断a和flag是否相同,相同则输出flag
该如何使a和flag相同,
查strcmp函数比较字符串的本质是将两个变量转换为ascii,然后进行减法运算。但Php5.3之后版本使用strcmp比较一个字符串和数组的话,将不再返回-1而是返回0
所以我们直接把a变为数组就行了
Payload:?a[]=12

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";
}
?>

分析:传入的参数为id,先判断id是否为hackerDJ,再令id进行urldecode后等于hackerDJ。但别忘记了浏览器会先进行一次解码再到函数解码。所以要加密两次。
D的第一次加密为%44,再加密一次%2544,因为44无法继续加密,而%还能加密为%25所以得到的PayLoad为:?id=hacker%2544J

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';
}
?>

分析:首先要传入两个参数分别为username和password这两个,然后他们两个要不为NULL,再然后他们不能相等,最后他们的md5加密要相同。
最后一步是关键点,有两种方法第一种找md5碰撞的,第二种根据数组进行MD5加密报错返回值为NULL使之相等。
我采用第二种
Payload:?username[]=1&password[]=2

数组返回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';
}
?>

分析传入的参数为password,password要不为NULL,
ereg() 正则限制了password格式,只能是一个或者多个数字、大小写字母。但可以通过%00截断绕过正则匹配
strpos() 函数查找字符串在另一字符串中第一次出现的位置。要求存在—但不能为开头。
payload:?password[]=1或?password=1%00–

弱类型整数大小比较绕过

$temp = $_GET['password'];
is_numeric($temp)?die("no numeric"):NULL;
if($temp>1336){
echo $flag;

分析:
把password的值赋给temp,
is_numeric() 函数用于检测变量是否为数字或数字字符串,可以通过16进制绕过,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后。
Temp的值不能为数字或数字字符串
temp值要大于1336
payload:?password=10000%00或?password=1553abc,1553abc由于类型转换变为了1553与1336进行对比

sha()函数比较绕过

<?php
$flag = "flag";
if (isset($_GET['name']) and isset($_GET['password']))
{
	var_dump($_GET['name']);
	echo "";
	var_dump($_GET['password']);
	var_dump(sha1($_GET['name']));
	var_dump(sha1($_GET['password']));
	if ($_GET['name'] == $_GET['password'])
		echo 'Your password can not be your name!';
	else if (sha1($_GET['name']) === sha1($_GET['password']))
		die('Flag: '.$flag);
	else
		echo 'Invalid password.';
}
else echo 'Login first!';
?>

分析:
传入name和password两个参数,不为null。Name和password值不能相等
name和password进行Sha1加密后要相等。
Sha1和md5绕过原理一样
Payload:?name[]=1&password[]=2

md5加密相等绕过

<?php
$md51 = md5('QNKCDZO');
$a = @$_GET['a'];
$md52 = @md5($a);
if(isset($a))
{
	if ($a != 'QNKCDZO' && $md51 == $md52) 
	{
		echo "flag{*}";
	}
	 else {
		echo "false!!!";}
}
else{echo "please input a";}
?>

分析:
Md51的值为 QNKCDZO的md5加密后的结果
a = @ a=@ a=@_GET[“a”]; 其中的 @ 是为了防止没有 G E T [ ′ a ′ ] 出 现 错 误 提 示 把 a 的 值 进 行 m d 5 加 密 存 放 在 m d 52 a 不 能 为 N U L L , 且 不 等 于 Q N K C D Z O , 但 _GET['a']出现错误提示 把a的值进行md5加密存放在md52 a不能为NULL,且不等于QNKCDZO,但 GET[a]amd5md52aNULLQNKCDZOmd51 = $md52这里可以利用==来对哈希值进行比较,0e开头都解释为0,找常见md5碰撞的值
payload:?a=s155964671a

十六进制与数字比较

<?php
error_reporting(0);
function noother_says_correct($temp)
{
	$flag = 'flag{test}';
	$one = ord('1'); //ord — 返回字符的 ASCII 码值
	$nine = ord('9'); //ord — 返回字符的 ASCII 码值
	$number = '3735929054';
	// Check all the input characters!
	for ($i = 0; $i < strlen($number); $i++)
	{
		// Disallow all the digits!
		$digit = ord($temp{$i});
		if ( ($digit >= $one) && ($digit <= $nine) )
		{
			// Aha, digit not allowed!
			return "flase";
		}
	}
	if($number == $temp)
	return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);
?>

分析:传入的参数为password,把1和9的ASCII算出来,如果password的值不能在1到9之间的,要求password的值和number的值一样。
不能在1到9之间那么就可以用0或者字母来表达,那么就要使用16进制来表达number的值
Payload:?password=0xdeadc0de

变量覆盖

打不开跳过

ereg正则%00截断

<?php
$flag = "xxx";
if (isset ($_GET['password']))
{ 
	if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
 		{ echo 'You password must be alphanumeric'; } 
	else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999) 
		{ if (strpos ($_GET['password'], '-') !== FALSE)
		 //strpos — 查找字符串首次出现的位置 
			{ die('Flag: ' . $flag); } 
		else { echo('- have not been found'); } 
} 
else { echo 'Invalid password'; } 
}?>

代码整理后如上
分析:传入的参数为password且要求设置好不为null,使用ereg正则限制password值,但可以通过%00截断绕过正则匹配
要求password的值的长度不超过8且数值大于9999999,看着很冲突,但我们可以改为科学计数法表达10000000=1e8
寻找Password的-且不等于false,
?password=1e8%00-然后出现问题*-* have not been found
他要寻找的是*-,修改下
Payload:?password=1e8%00
-*或?password[]=1

strpos数组绕过

<?php
$flag = "flag";
if (isset ($_GET['ctf'])) {
	if (@ereg ("^[1-9]+$", $_GET['ctf']) === FALSE)
		echo '必须输入数字才行';
	else if (strpos ($_GET['ctf'], '#biubiubiu') !== FALSE)
		die('Flag: '.$flag);
	else
		echo '骚年,继续努力吧啊~';
}
?>

分析:存入的参数为ctf且不能为NULL
使用ereg正则限制ctf值,但可以通过%00截断绕过正则匹配,但数组好像也能绕过
要在ctf中寻找到#biubiubiu
Payload:?ctf[]=#biubiubiu

**

数字验证正则绕过

**

<?php
error_reporting(0);
$flag = 'flag{test}';
if ("POST" == $_SERVER['REQUEST_METHOD'])
{
	$password = $_POST['password'];
	if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 执行一个正则表达式匹配
	{
		echo 'flag';
		exit;
	}
	while (TRUE)
	{
		$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
		if (6 > preg_match_all($reg, $password, $arr))
			break;
		$c = 0;
		$ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何标点符号 [[:digit:]] 任何数字 [[:upper:]] 任何大写字母 [[:lower:]] 任何小写字母
		foreach ($ps as $pt)
		{
			if (preg_match("/[[:$pt:]]+/", $password))
				$c += 1;
		}
		if ($c < 3) break;
		//>=3,必须包含四种类型三种与三种以上
		if ("42" == $password) echo $flag;
		else echo 'Wrong password';
		exit;
	}
}
?>

分析:
Post传输,
正则匹配,[:graph:]为任意字符,要求password长度超过12
password中必须包含标点符号,数字,大写字母,小写字母,并且检测次数要超过6次
c为字符种类
必须包含四种类型三种与三种以上
弱类型比较,42abc,强制转换为数字
蛮奇怪的最后要求是用flag参数
Payload:flag=42aaaaaaa.aaaaaaa

简单的waf

题目打不开!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值