代码审计类ctf记录

1.php strcmp()漏洞

1
int strcmp ( string $str1 , string $str2 )

参数 str1第一个字符串。str2第二个字符串。如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0
该漏洞是用于php5.3之前的版本
该函数要求是上传字符串进行比较,当我们传入非法参数时,如数组,在php5.3之前函数会报错,return 0!刚好和两个字符串相等返回0的结果一样

1
2
3
4
5
6
7
8
9
10
11
12
13
$pass=@$_POST['pass'];
$pass1=***********;//被隐藏起来的密码
if(isset($pass))
{
if(@!strcmp($pass,$pass1)){
echo "flag:nctf{*}";
}else{
echo "the pass is wrong!";
}
}else{
echo "please input pass!";
}
?>

payload:pass[]=1

2.php://输入输出流

输入输出流主要包括三种:
php://input:直接读取post上没有经过解析的原始数据

php://output:将post流数据输出

php://filter:(常用在XXE漏洞中)文件操作协议,对磁盘文件进行读写,类似于readflie()、file()、flie_get_conments()

image

1
2
3
$file = $_GET['file'];
if(@file_get_contents($file) == "meizijiu"){
echo $nctf;

这道题要的是获取flie传入的文件,提取内容与meizijiu进行比较,我们可以利用php://input
image

3.进制转换绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
function noother_says_correct($number)
{
$one = ord('1');
$nine = ord('9');
for ($i = 0; $i < strlen($number); $i++)
{
$digit = ord($number{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
return false;
}
}
return $number == '54975581388';
}
$flag='*******';
if(noother_says_correct($_GET['key']))
echo $flag;
else
echo 'access denied';
?>

这段代码要的是get参数key的值与54975581388相等,但是每一位字符串的assic码要在0到9之外,这里我们可以将54975581388十六进制转码成0xccccccccc绕过

又一道题
源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
you are not the number of bugku !   

<!--
$user = $_GET["txt"];
$file = $_GET["file"];
$pass = $_GET["password"];

if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){
echo "hello admin!<br>";
include($file); //hint.php
}else{
echo "you are not admin ! ";
}
-->

这里要求传入是三个参数txt、file、password

  • txt:txt参数传给了user变量,file_get_contents($user,’r’)===”welcome to the bugkuctf”,这里我们可以用到php输入流post传值
  • flie:刚开始我以为因为是include()函数我直接将file=hint.php就可以得出hint.php的值,这里没有考考虑到hint.php的路径问题,所以我们应该使用php://filter
  • password:这里没有对passwor进行限制,可以随意处置
    payload:?txt=php://input&file=php://filter/content.base64-encode/resoursce=hint.php
    post:welcome to the bugkuctf
    得到一个base64的代码,解码得到
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php  

class Flag{//flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("good");
}
}
}
?>

我再次用PHP://filter读取flag.php,它告诉我不能现在就给我flag,后面就搞不懂了

4.超全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php  

error_reporting(0);
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){ #判断args参数是否存在
$args = $_GET['args'];
if(!preg_match("/^\w+$/",$args)){#用正则判断看srgs变量中是否有字母及数字,有函数返回1,否0,所以这里让你只能输入字母和数字
die("args error!");
}
eval("var_dump($$args);");
}
?>

这道题的关键是var_dump函数输出变量的类型和内容,这里就要抠脑壳了,怎么知道flag在哪个变量
看书才发现可以使用$GLOBALS超全局数组调用系统中的所有变量和常量以及对象和对象中的属性变量值
$GLOBALS 这种全局变量用于在 PHP 脚本中的任意位置访问全局变量(从函数或方法中均可)。
PHP在名为$GLOBALS[index]的数组中存储了所有全局变量。变量的名字就是数组的键。
这样我们就给变量赋值args=GLOBALS,使变量为存储了所有变量的数字

5.变量覆盖+php输入输出流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$flag='xxx';
extract($_GET);#存在变量覆盖漏洞
if(isset($shiyan))
{
$content=trim(file_get_contents($flag));#看到file_get_contents想到PHP://输入输出
if($shiyan==$content)
{
echo'flag{xxx}';
}
else
{
echo'Oh.no';
}
}
?>

因为这两种漏洞都写了,只是记住了一道题可以运用多种方法混合区解答
image
get传参利用了变量覆盖,将shiyan与content都赋值为0从而绕过,但是由于在覆盖变量之后,会给content重新赋值,所以看到了file_get_contents函数,想到了PHP输入流post传参,通过修改flag的值将content值进行修改

6.URLencode二次编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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函数在id参数中查找有没有hackerDJ字符,有则返回0,所以这里我们不能直接赋值hackerDJ,题目提示了二次编码,这里的get传参时已经进行了一次urldecode解码,后面又通过urldecode函数进行了二次解码,所以经过上面这些提示,就是对hackerDJ进行urlencode二次编码,传入参数就是hackerDJ,又到了抠脑壳的时候,为什么hackerDJ用工具编码后还是不变,看了人家的解答后才知道这种纯字符是不能用工具解码的,要对照编码表解码
image
image

7.数组返回NULL绕过or%00截断

1
2
3
4
5
6
7
8
9
10
11
12
<?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';
}
?>

ereg函数查找password

8.一道综合题

never never never give up!!!
这道题点开源码发现提示

1
2
3
<!--1p.html-->
never never never give up !!!

于是打开1p.html,但是发现重定向了,于是直接view-source:得到一串base64编码的代码

1
JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ==

解码得

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
if(!$_GET['id'])
{
header('Location: hello.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
echo 'no no no no no no no';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
require("f4l2a3g.txt");
}
else
{
print "never never never give up !!!";
}


?>

这里设置了三个get参数id、a、b,分别对应了三种不同的代码绕过机制

  • id:关于id的值id==0,并不是说是字符零,而是数字0,所以我们只需要给id赋值一个无数字字符串,无数字字符串在比较时会强制类型转换为数字0
  • a:a必须为“bugku is a nice plateform!”首先一个stripos($a,’.’)函数,限制了a不能从外部引用文件,但又出现了file_get_contents,我们想到了input输入流的形式进行post传参
  • b:b的长度通过strlen($b)>5限制为5以内,eregi(“111”.substr($b,0,1),”1114”)表示b中必须要有4,但是substr($b,0,1)!=4,所以我们想到了%00截断

构造payload:?id=@&a=php://input&b=%0044444 ,
post:bugku is a nice plateform!

9.正则表达式匹配

1
2
3
4
5
6
7
8
 <?php 
highlight_file('2.php');
$key='KEY{********************************}';
$IM= preg_match("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match);
if( $IM ){
die('key is: '.$key);
}
?>

这道题考察的是正则表达式的匹配

/key.*key.{4,7}key:/./(.*key)[a-z][[:punct:]]/i

首先是一个字符串key,后面.表示匹配除/n之外的所有单字符,*表示前面的单字符重复0次或多次,.{4,7}又表示重复除/n以外的单字符4到7次,后面再跟字符串key:,这里\/将/转义,后面(.*key)就是单字符+key,[a-z]表示从中选一个字母,[[:punct:]]表示匹配标点符号
payload:?id=key.key…..key:/./.keya;

10.INSERT INTO注入

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
error_reporting(0);#没有报错回显

function getIp(){#获取真实ip
$ip = '';
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){#先查看X-Forworded-For头是否设置,取其值
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
$ip = $_SERVER['REMOTE_ADDR'];
}
$ip_arr = explode(',', $ip);#将ip变量中的字符串以,为间隔打散成数组
return $ip_arr[0];#所以后面构造sql语句时不能出现,

}

$host="localhost";
$user="";
$pass="";
$db="";

$connect = mysql_connect($host, $user, $pass) or die("Unable to connect");#链接数据库

mysql_select_db($db) or die("Unable to select database");#查询数据库

$ip = getIp();
echo 'your ip is :'.$ip;
$sql="insert into client_ip (ip) values ('$ip')" ;#向client_ip表中插入变量ip的值
mysql_query($sql);
文章目录
  1. 1. 1.php strcmp()漏洞
  2. 2. 2.php://输入输出流
  3. 3. 3.进制转换绕过
  4. 4. 4.超全局变量
  5. 5. 5.变量覆盖+php输入输出流
  6. 6. 6.URLencode二次编码
  7. 7. 7.数组返回NULL绕过or%00截断
  8. 8. 8.一道综合题
  9. 9. 9.正则表达式匹配
  10. 10. 10.INSERT INTO注入
,