概述
代碼審計(jì)顧名思義就是檢查源代碼中的缺點(diǎn)和錯(cuò)誤信息李破,分析并找到這些問題引發(fā)的安全漏洞哲虾,并提供代碼修訂措施和建議。這篇文章的目的是為了讓小伙伴們對php代碼審計(jì)有一個(gè)基本的了解,采用的代碼都是自己寫的僅僅能體現(xiàn)出漏洞所以會略顯簡潔。并且這次文章的主要內(nèi)容為代碼審計(jì)所以不會寫太多的注入語句响禽,更多的是對代碼的分析,有興趣的同學(xué)可以百度查查資料荚醒。
環(huán)境要求
phpstudy和一篇簡單易懂的php源碼
sql注入
SQL 注入(SQL Injection) 是發(fā)生在 Web 程序中數(shù)據(jù)庫層的安全漏洞芋类,是網(wǎng)站存在最多也是最簡單的漏洞。 主要原因是程序?qū)τ脩糨斎霐?shù)據(jù)的合法性沒有判斷和處理界阁,導(dǎo)致攻擊者可以在 Web 應(yīng)用程序中事先定義好的 SQL 語句中添加額外的 SQL 語句侯繁,在管理員不知情的情況下實(shí)現(xiàn)非法操作,以此來實(shí)現(xiàn)欺騙數(shù)據(jù)庫服務(wù)器執(zhí)行非授權(quán)的任意查詢泡躯,從而進(jìn)一步獲取到數(shù)據(jù)信息贮竟。 簡而言之,SQL 注入就是在用戶輸入的字符串中加入 SQL 語句较剃,如果在設(shè)計(jì)不良的程序中忽略了檢查坝锰,那么這些注入進(jìn)去的 SQL 語句就會被數(shù)據(jù)庫服務(wù)器誤認(rèn)為是正常的 SQL 語句而運(yùn)行,攻擊者就可以執(zhí)行計(jì)劃外的命令或訪問未被授權(quán)的數(shù)據(jù)重付。
一、union查詢注入
union查詢注入是MySQL注入中的一種方式凫乖,在SQL注入中說了注入漏洞存在的相關(guān)條件确垫,而聯(lián)合查詢注入這種方法需要滿足查詢的信息在前端有回顯,回顯數(shù)據(jù)的位置就叫回顯位帽芽。
源代碼
<?php
? ? ? ? require 'db.php';
? ? ? ? header('Content-type:text/html;charset=utf8');
? ? ? ? $username=$_POST["username"]; //獲取用戶輸入
? ? ? ? $password=$_POST["password"];
? ? ? ? $dl="SELECT * FROM xs WHERE username='$username' and password='$password'"; //登錄界面后臺處理
? ? ? ? $ck=mysqli_query($db,$dl);
? ? ? ? $row = mysqli_fetch_array($ck);
? ? ? ? if($row) {
? ? ? echo "你的賬號為:".$row['username'];
? ? ? echo "你的密碼為:".$row['password'];
? ? ? ? } else {
echo "你的輸入" .$username;
}
這段代碼一上來加載了一個(gè)文件db.php根據(jù)名字可以判斷是連接數(shù)據(jù)庫文件删掀,接著設(shè)置編碼為UTF8,然后獲取用戶輸入的賬號和密碼設(shè)置為變量导街,賦入sql查詢語句判斷賬號密碼是否輸入正確披泪,利用query執(zhí)行sql語句,再用mysqli_fetch_array把結(jié)果作為數(shù)組輸出到row中搬瑰。最后用if語句判斷sql語句是否執(zhí)行款票,執(zhí)行成功輸出用戶的賬號和密碼,執(zhí)行失敗會輸出用戶輸入的賬號泽论。代碼沒有任何防御艾少,有兩個(gè)回顯位所以直接union注入。
注入語句為-1' union select 1,2? #
二翼悴、sql盲注
所謂的盲注就是在服務(wù)器沒有錯(cuò)誤回顯的時(shí)候完成的注入攻擊缚够。服務(wù)器沒有錯(cuò)誤回顯,對于攻擊者來說缺少了非常重要的“調(diào)試信息
源代碼
<?php
? ? ? ? require 'db.php';
? ? ? ? header('Content-type:text/html;charset=utf8');
? ? ? ? $username=$_POST["username"]; //獲取用戶輸入
? ? ? ? $password=$_POST["password"];
? ? ? ? $dl="SELECT * FROM xs WHERE username='$username' and password='$password'"; //登錄界面后臺處理
? ? ? ? $ck=mysqli_query($db,$dl);
? ? ? ? $row = mysqli_fetch_array($ck);
? ? ? ? if($row) {
? ? ? ? ? ? echo "你的輸入" .$username;
? ? ? ? } else {
echo "輸入錯(cuò)誤" ;
}
代碼和上面聯(lián)合查詢基本一樣只是執(zhí)行成功以后沒有了回顯,只返回成功和失敗谍椅,我們可以使用用布爾盲注通過返回構(gòu)造的注入語句正確與否來獲取數(shù)據(jù)庫里的信息误堡。
注入語句
1' and length(database())=3 #?
三、sql延時(shí)注入
時(shí)間差注入也叫延遲注入雏吭,是一種盲注的手法提交對執(zhí)行時(shí)間銘感的函數(shù)sql語句锁施,通過執(zhí)行時(shí)間的長短來判斷是否執(zhí)行成功,比如:正確的話會導(dǎo)致時(shí)間很長思恐,錯(cuò)誤的話會導(dǎo)致執(zhí)行時(shí)間很短沾谜,這就是所謂的高級盲注。
源代碼
<?php
? ? ? ? require 'db.php';
? ? ? ? header('Content-type:text/html;charset=utf8');
? ? ? ? $username=$_POST["username"]; //獲取用戶輸入
? ? ? ? $password=$_POST["password"];
? ? ? ? $dl="SELECT * FROM xs WHERE username='$username' and password='$password'"; //登錄界面后臺處理
? ? ? ? $ck=mysqli_query($db,$dl);
? ? ? ? $row = mysqli_fetch_array($ck);
? ? ? ? if($row) {
? ? ? ? ? ? echo "你的輸入" .$username;
? ? ? ? } else {
? ? ? ? ? ? echo "你的輸入" .$username;
}
這次執(zhí)行成功和失敗返回的結(jié)果一模一樣布爾盲注的方法也不行了胀莹,我們可以使用延時(shí)注入語句讓瀏覽器語句執(zhí)行成功的同時(shí)延時(shí)五秒基跑,延時(shí)注入一般用if()加sleep語句配合burpsuite。
注入語句
1' and if((length(database())=3),sleep(5),1) #
四描焰、報(bào)錯(cuò)注入
報(bào)錯(cuò)注入就是利用了數(shù)據(jù)庫的某些機(jī)制媳否,人為地制造錯(cuò)誤條件,使得查詢結(jié)果能夠出現(xiàn)在錯(cuò)誤信息中荆秦。
源代碼
<?php
? ? require 'db.php';
? ? header('Content-type:text/html;charset=utf8');
? ? $username = $_POST["username"]; //獲取用戶輸入
? ? $password = $_POST["password"];
? ? $dl = "SELECT * FROM xs WHERE username='$username' and password='$password'"; //登錄界面后臺處理
? ? $ck = mysqli_query($db, $dl);
? ? $row = mysqli_fetch_array($ck);
if($row)
{
? echo "登錄成功";
? }
else
{
print_r(mysql_error());
}
}
報(bào)錯(cuò)注入就是利用返回錯(cuò)誤信息的函數(shù)篱竭,把注入的結(jié)果通過錯(cuò)誤信息返回來,這里可以看到代碼執(zhí)行失敗以后會調(diào)用報(bào)錯(cuò)函數(shù)步绸,可以直接在賬號框里構(gòu)造報(bào)錯(cuò)注入代碼掺逼,下面示范采用的updatexml語句。報(bào)錯(cuò)注入常用的有floor,updatexml,extractvalue這三種瓤介。
注入語句
admin") and updatexml(1,concat(0x7e,(select database()) ,0x7e),1) #
五吕喘、cookie注入
Cookie注入簡單來說就是利用Cookie而發(fā)起的注入攻擊。從本質(zhì)上來講刑桑,Cookie注入與傳統(tǒng)的SQL注入并無不同氯质,兩者都是針對數(shù)據(jù)庫的注入,只是表現(xiàn)形式上略有不同罷了祠斧。
先來看看源碼
require 'db.php';
header('Content-type:text/html;charset=utf8');
$username=addslashes($_POST['username']);
$password=MD5($_POST['password']);
$dl="SELECT * FROM xs WHERE username='$username' and password='$password'"; //登錄界面后臺處理
$ck=mysqli_query($db,$dl);
$row = mysqli_fetch_array($ck);
if($_POST['login']){
if($row) {
setcookie('uname',$row['username']);
$cooke=$_COOKIE['uname'];
$ql="select * from xs where username='$cooke'";
$qk=mysqli_query($db,$ql);
$row1 = mysqli_fetch_array($qk);
if($row1){
echo "nidecooke 創(chuàng)建成功";
}
}
}?>
可以看到cookie注入和上面的代碼有很大的區(qū)別闻察。前面一大段是正常的登錄判斷語句,賬號用了addslashes()語句進(jìn)行轉(zhuǎn)義琢锋,密碼通過MD5加密辕漂。而cookie語句在if($row)主體里,也就是說只有我們繞過了或者輸入正確的賬號和密碼才會去創(chuàng)建cookie吴超。創(chuàng)建cookie以后帶入了sql語句里直接執(zhí)行钮热。從代碼上面來看注入位置不在登錄框在cookie里。cookie查詢語句執(zhí)行完以后也沒有回顯烛芬,所以我們在cooki位置用布爾盲注試試隧期。先用burpsuite抓包就能看見cookie了飒责。切記在注入的時(shí)候一定要輸入正確的賬號和密碼也就是if($row)需要返回正確的值下面的語句才會執(zhí)行。
可以看到uname=1 uname是上面代碼中創(chuàng)建的cookie我們只需在在這個(gè)位置進(jìn)行布爾盲注就可以拿到想要的數(shù)據(jù)仆潮。
構(gòu)造這個(gè)獲取當(dāng)前數(shù)據(jù)庫長度語句返回成功說明當(dāng)前數(shù)據(jù)長度為3.
sql注入初級篇就完結(jié)了宏蛉,這一篇只是小打小鬧讓對代碼審計(jì)還不了解的同學(xué)有一個(gè)初步的認(rèn)識,接下來幾篇會為大家講解一些比較難和有防御措施的代碼性置。