CTF平台题库writeup(四)--BugKuCTF-代码审计(14题详解)

CTF平台题库writeup(四)--BugKuCTF-代码审计(14题详解)_第1张图片

1、extract变量覆盖

知识点:

变量覆盖

file_get_contents():将整个文件读入一个字符串

trim()去除字符串两侧的空格或者指定字符trim('string','string you want to delete')

$_GET:表示等一下提交变量时,URL 通过 get 的方式传参,传输的数据以数组的形式被封装在$_GET 中。

extract():从数组中将变量导入到当前的符号表。该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。

利用extract()函数的变量覆盖漏洞原理构造payload

漏洞产生原因:extract()函数当只有一个参数时,默认的第二参数是:EXTR_OVERWRITE,如果有变量发生冲突,则覆盖已有的变量。

思路:

代码审计需要满足两个条件:

1. if(isset($shiyan))  == 》 TRUE

2. if(shiyan==shiyan==content)  == 》 TRUE

 

//利用extract()函数变量覆盖漏洞+php伪协议

//利用file_get_content()函数返回字符串+php弱类型(null == "string"  ==》 true

弱类型

http://123.206.87.240:9009/1.php?shiyan=

http://123.206.87.240:9009/1.php?shiyan=&flag=

http://123.206.87.240:9009/1.php?shiyan=&content=

伪协议(有点奇怪此题,用伪协议居然没有显示flag)

http://123.206.87.240:9009/1.php?shiyan=123&file=php://input

123

2、strcmp比较字符串

http://123.206.87.240:9009/6.php

 0;如果两者相等,返回 0。
//比较两个字符串(区分大小写)
die('Flag: '.$flag);
else
print 'No';
}
?>

知识点:

die() 函数输出一条消息,并退出当前脚本。

strcmp(str1, str2)比较两个字符串大小,若是非字符串(例如数组)比较,则会出错。在5.3之前的php中,显示了报错的警告信息后,将return 0。0==0执行
payload:?a[]=1

3urldecode二次编码绕过

http://123.206.87.240:9009/10.php

 

eregi()在一个字符串中搜索指定的模式的字符串,搜索不区分大小的正则匹配。
urldecode()解码以编码的URL字符串,但是$_GET[]会将参数解码一次。

若本题将“hackerDJ”进行两次URL编码,在eregi()中比较”hackerDJ”与$_GET[id]是否相同,$_GET会解码一次,从二次URL编码变成一次URL编码;urldecode()会将$_GET[id]从二次URL编码变成一次URL编码,赋值给$_GET[id],当$_GET[id]与“hackerDJ”比较时,$_GET[id]再从一次URL编码解码,最后比较相等得到flag。

将“hackerDJ”进行两次URL编码。

Payload(hackerDJ 可以全部字母或者个别字母做二次urlEncode)

http://123.206.87.240:9009/10.php?id=%25%36%38%25%36%31%25%36%33kerDJ

或者

http://123.206.87.240:9009/10.php?id=%25%36%38%25%36%31%25%36%33%25%36%62%25%36%35%25%37%32%25%34%34%25%34%61

4md5()函数

http://123.206.87.240:9009/18.php

<

?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()计算字符串的MD5散列值。
md5()函数不能处理数组,使用数组绕过,md5(array)会返回null。

Payload:

http://123.206.87.240:9009/18.php?username[]=1&password[]=2

5数组返回NULL绕过

http://123.206.87.240:9009/19.php

strpos(string, find[, start])查找字符串在另一字符串中第一次出现的位置。

ereg()正则匹配,需使password中只含有英文字母和数字,又因为strpos()需要匹配“–”才能得到flag,可以使用数组绕过ereg()和strpos()。

ereg()只能处理字符,而password是数组,所以返回的是null,三个等号的时候不会进行类型转换。所以null!==false。

strpos()的参数同样不能够是数组,所以返回的依旧是null,null!==false也是正确。

payload:?password[]=1

http://123.206.87.240:9009/19.php?password[]=1

思路二:ereg()可以进行%00截断,绕过正则匹配。

payload:?password=1%00--

http://123.206.87.240:9009/19.php?password=jjjk%00--

6弱类型整数大小比较绕过

http://123.206.87.240:9009/22.php

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

is_numeric(var)检测变量是否为数字或数字字符串,是则返回true,否则返回false。

is_numeric()对于空字符%00,无论%00放在前面还是后面都可以判断为非数值,而空格%20只能放在数值后面,实质上都是弱类型转换。

payload1:?password=1337%00

payload2:?password=1337%20

payload3:?password=1337a

7、sha()函数比较绕过



同md5()一样,sha1()函数也无法处理数组,因此可以构造数组绕过。

http://123.206.87.240:9009/7.php?password[]=1&name[]=2

array(1) { [0]=> string(1) "2" }
array(1) { [0]=> string(1) "1" } NULL NULL Flag: flag{bugku--daimasj-a2}

8、md5加密相等绕过
http://123.206.87.240:9009/13.php

md5生成的以“0e”开头的哈希值都解释为0,所以PHP在判断时会认为相同

PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以“0E”开头的哈希值都解释为0,

如果两个不同的值经过哈希以后,都是0E开头,那么PHP将会认为他们相同


这里提供一个
s878926199a

http://123.206.87.240:9009/13.php?a=s155964671a

举例:md5后以0e开头的字符串

240610708

0e462097431906509019562988736854

QNKCDZO

0e830400451993494058024219903391

s878926199a

0e545993274517709034328855841020 

s155964671a

0e342768416822451524974117254469

s214587387a

0e848240448830537924465865611904

s214587387a

0e848240448830537924465865611904

s878926199a

0e545993274517709034328855841020

9、十六进制与数字比较

http://123.206.87.240:9009/20.php

= $one) && ($digit <= $nine) )
{
// Aha, digit not allowed!
return "flase";
}
}
if($number == $temp)
return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);
?>

ord()返回字符串中首个字符的ASCII值。
题目中会要求输入的password中不能有0~9数字,并且还需要判断$number==$_GET[password]。所以将$number=3735929054转换为16进制“deadc0de”,再在前面加上0x表示16进制。

http://123.206.87.240:9009/20.php?password=0xdeadc0de

10、变量覆盖(地址访问不了)

http://120.24.86.145:9009/bianliang/

11、ereg正则%00截断

http://123.206.87.240:9009/5.php

 9999999)
{
if (strpos ($_GET['password'], '-') !== FALSE) //strpos — 查找字符串首次出现的位置
{
die('Flag: ' . $flag);
}
else
{
echo('

- have not been found

');
}
}
else
{
echo '

Invalid password

';
}
}
?>

题目通过ereg()函数判断password中是否只含有字母或数字,进而限制password长度小于8,并且值小于9999999;在此前提下用strpos()函数搜索password中是否含有“-”,若是则输出flag。

解法一,利用数组绕过strpos()函数。strpos()数组 null!=false, strlen()数组长度为0

payload:?password[]=9999999999

解法二,利用ereg()%00截断漏洞,在用科学记数法来构造1e9满足strlen($_GET[‘password’]) < 8 && $_GET[‘password’]> 9999999这个条件,再加上“-”来满足strpos()的条件。

payload:?password=1e9%00*-*

12、strpos数组绕过

http://123.206.87.240:9009/15.php

构造数组绕过,并且值含有数字。
payload:?ctf[]=1

 

?ctf=12333%00#biubiubiu 此种方式不可,因为ereg()存在%00截断,而strpos()则不存在

13、数字验证正则绕过

http://123.206.87.240:9009/21.php

= 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一个password就可以,并且小于12个字符。

payload:

http://123.206.87.240:9009/21.php

POST:password=1

 

 

14、简单的waf

http://120.24.86.145:9010/        

服务器坏了,网上找的wp

要求传入abcde,a中不能包含php,因此a不能用php://input来为其赋值了,但是可以通过远程文件包含来为其赋值,即在自己的服务器上写一个txt文件,e可以用php://input来赋值,然后就会看到返回hello admin

CTF平台题库writeup(四)--BugKuCTF-代码审计(14题详解)_第2张图片

但是 c和d不知道有什么作用,看到c中不能包含flag,d不能包含base64,于是猜测题目可能存在flag.php之类的,需要通过d去读取?尝试访问flag.php看到flag on my head,访问flag,发现会下载一个文件,里面说Please call admin to get flag,令c=flag.php会触发他的waf,但是令c=Flag.php可以绕过,但是也没有返回其他的东西,摇头.gif不知道怎么操作了,希望有大佬会的话带带我Orz

你可能感兴趣的:(bugku,CTF,信息安全,安全)