PHP代码审计-萌新之路(二)

本文承接上文PHP代码审计-萌新之路(一),由于博主也是萌新,自然也有不会做的题目,当然等博主技术足够之后是会补充回来的。

0x04SQL注入_WITH ROLLUP绕过


error_reporting(0);

if (!isset($_POST['uname']) || !isset($_POST['pwd'])) {
    echo '
'."
"
; echo ''."
"
; echo ''."
"
; echo ''."
"
; echo ''
."
"
; echo ''."
"
; die; } function AttackFilter($StrKey,$StrValue,$ArrReq){ if (is_array($StrValue)){ //检测变量是否是数组 $StrValue=implode($StrValue); //返回由数组元素组合成的字符串 } if (preg_match("/".$ArrReq."/is",$StrValue)==1){ //匹配成功一次后就会停止匹配 print "水可载舟,亦可赛艇!"; exit(); } } $filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)"; foreach($_POST as $key=>$value){ //遍历数组 AttackFilter($key,$value,$filter); } $con = mysql_connect("XXXXXX","XXXXXX","XXXXXX"); if (!$con){ die('Could not connect: ' . mysql_error()); } $db="XXXXXX"; mysql_select_db($db, $con); //设置活动的 MySQL 数据库 $sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'"; $query = mysql_query($sql); //执行一条 MySQL 查询 if (mysql_num_rows($query) == 1) { //返回结果集中行的数目 $key = mysql_fetch_array($query); //返回根据从结果集取得的行生成的数组,如果没有更多行则返回 false if($key['pwd'] == $_POST['pwd']) { print "CTF{XXXXXX}"; }else{ print "亦可赛艇!"; } }else{ print "一颗赛艇!"; } mysql_close($con); ?>

待定

0x05ereg正则%00截断

 

$flag = "flag";

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参数是否存在
第二个判断ereg函数()用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。(不敏感就是eregi函数)
也就是我们传入的password必须是字母和数字,好那么看到第三个判断
我们传入的数字位数得小于八位而且得大于9999999,这里我们可以构造科学计数法,也就是1e9
最后一个判断就是查找字符串在password参数里是否存在*—,存在即输出flag
这里第一种解法:
ereg正则%00截断(原理:ereg读到%00的时候,就截止了)
由于ereg只能传入数字和字母所以
-*传入肯定是不行的,我们构造

\?password=1e9%00*-*

将*-给截断,ereg函数就不会读后面这个-*了
第二种解法:
传入一个password数组

\?password[]=1

ereg函数只能处理字符串,而password被我们传入了数组,所以返回值是null,全等不会进行类型转换,所以null!==false
而strops()函数也只能处理字符串,所以 NULL!==flase也成立,数组判断大小是直接返回true的。

0x06strcmp比较字符串


$flag = "flag";
if (isset($_GET['a'])) {  
    if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。 

    //比较两个字符串(区分大小写) 
        die('Flag: '.$flag);  
    else  
        print 'No';  
}
?>

strcmp()函数判断数组也是返回NULL,而NULL==0 是 bool(true)的,可以自己var_dump试试
所以payload:

/?a[]=1

0x07sha()函数比较绕过



$flag = "flag";

if (isset($_GET['name']) and isset($_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!

'
; ?>

sha1这个函数也一样
举个例子


$a = array(1);
$b = array(2);
var_dump(sha1($a)===sha1($b));

遇事不决,var_dump
故此题payload:

/?name[]=1&password[]=2

0x08session验证绕过



$flag = "flag";

session_start(); 
if (isset ($_GET['password'])) {
    if ($_GET['password'] == $_SESSION['password'])
        die ('Flag: '.$flag);
    else
        print '

Wrong guess.

'
; } mt_srand((microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000)); ?>

当传入的password==session的password的时候输出flag
删除cookies或者删除cookies的值,然后将password值传为空就可以

/?password=

0x09密码md5比较绕过



//配置数据库
if($_POST[user] && $_POST[pass]) {
    $conn = mysql_connect("********, "*****", "********");
    mysql_select_db("phpformysql") or die("Could not select database");
    if ($conn->connect_error) {
        die("Connection failed: " . mysql_error($conn));
} 

//赋值

$user = $_POST[user];
$pass = md5($_POST[pass]);

//sql语句

// select pw from php where user='' union select 'e10adc3949ba59abbe56e057f20f883e' # 

// ?user=' union select 'e10adc3949ba59abbe56e057f20f883e' #&pass=123456

$sql = "select pw from php where user='$user'";
$query = mysql_query($sql);
if (!$query) {
    printf("Error: %s\n", mysql_error($conn));
    exit();
}
$row = mysql_fetch_array($query, MYSQL_ASSOC);
//echo $row["pw"];

  if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {

//如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。


    echo "<p>Logged in! Key:************** </p>";
}
else {
    echo("<p>Log in failure!</p>");

  }
}
?>

待定

0x010urldecode二次编码绕过


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

not allowed!

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

Access granted!

"
; echo "

flag: *****************}

"
; } ?>

可以看到这里进行了一个urldecode操作,那么我们只需要将h进行两次url编码,然后将%进行url编码就可以绕过了,因为浏览器会进行一次url解码,构造id=%2568ackerDJ,%25会被解码为%和68进行拼接,然后经过urldecode就是h和后面ackerDJ拼接满足条件输出flag。

0x11sql闭合绕过


if($_POST[user] && $_POST[pass]) {
    $conn = mysql_connect("*******", "****", "****");
    mysql_select_db("****") or die("Could not select database");
    if ($conn->connect_error) {
        die("Connection failed: " . mysql_error($conn));
} 
$user = $_POST[user];
$pass = md5($_POST[pass]);
//select user from php where (user='admin')#
//exp:admin')#
$sql = "select user from php where (user='$user') and (pw='$pass')";
$query = mysql_query($sql);
if (!$query) {
    printf("Error: %s\n", mysql_error($conn));
    exit();
}
$row = mysql_fetch_array($query, MYSQL_ASSOC);
//echo $row["pw"];
  if($row['user']=="admin") {
    echo "

Logged in! Key: ***********

"
; } if($row['user'] != "admin") { echo("

You are not admin!

"
); } } ?>

可以看到,当$row[‘user’]=='admin’时,就会输出flag。
这里我们把几个操纵MySQL数据库的函数总结一下

mysql_connect() 函数打开非持久的 MySQL 连接。
mysql_select_db() 函数设置活动的 MySQL 数据库。
mysql_query() 函数执行一条 MySQL 查询。
mysql_fetch_array() 函数从结果集中取得一行作为关联数组

看看这条sql语句

select user from php where (user='$user') and (pw='$pass')

也就是说,我们可以post传入user变量为
admin') #就可以成功使$row['user']=='admin'
即可获取flag

后言

放心,还会有续集的,点赞和评论将会作为我写作最大动力,虽说白嫖很香,但是点赞和评论应该不算很麻烦,当然前提是您觉得我这篇文章写的不错,对您有用。如果觉得写的还行,请动动小手给我一个小小的赞,谢谢

你可能感兴趣的:(PHP代码审计)