裏面不少都是像laterain學習到的, 若是能考上cuit的話 自動獻菊花了。javascript
首先拿到一份源碼 確定是先install上。 而在安裝文件上又會常常出現問題。php
通常的安裝文件在安裝完成後 基本上都不會自動刪除這個安裝的文件 我遇到過的會自動刪除的好像也就qibocms了。html
其餘的基本都是經過生成一個lock文件 來判斷程序是否安裝過了 若是存在這個lock文件了 就會退出了。 這裏首先 先來講一下安裝文件常常出現的問題。java
這種的雖然很少 可是有時仍是會遇到個。 在安裝完成後 並不會自動刪除文件 又不會生成lock來判斷是否安裝過了。 致使了能夠直接重裝過mysql
例子: WooYun: PHPSHE B2C 重裝。linux
由於install 通常都會有step 步驟啥的。。 Step 1 check 啥啥 step 2 是安裝啥的。 而一些cms 默認step是1 而step又是GET 來的 而他check lock的時候就是在step1裏面。 這時候若是咱們直接用GET提交step 2 那麼就直接進入下一步了 就沒check lock了。程序員
例如某cms中的安裝文件web
if (empty ($step)) { $step = 1;//當用戶沒有提交step的時候 賦值爲1 } require_once ("includes/inc_install.php"); $gototime = 2000; /*------------------------ 顯示協議文件 ------------------------*/ if ($step == 1) //當1才檢測lock { if (file_exists('installed.txt')) { echo '<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> </head> <body> 你已經安裝過該系統,若是想從新安裝,請先刪除install目錄下的 installed.txt 文件,而後再安裝。 </body> </html>'; exit; } include_once ("./templates/s1.html"); exit (); } /*------------------------ 測試環境要求 ------------------------*/ else if ($step == 2) // 咱們直接提交step爲2 就不check lock了 { $phpv = @ phpversion(); $sp_os = $_ENV["OS"]; $sp_gd = @ gdversion(); $sp_server = $_SERVER["SERVER_SOFTWARE"]; $sp_host = (empty ($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_HOST"] : $_SERVER["SERVER_ADDR"]); $sp_name = $_SERVER["SERVER_NAME"]; $sp_max_execution_time = ini_get('max_execution_time'); $sp_allow_reference = (ini_get('allow_call_time_pass_reference') ? '<font color=green>[√]On</font>' : '<font color=red>[×]Off</font>'); $sp_allow_url_fopen = (in
header("Content-Type: text/html; charset={$lang}"); foreach(Array('_GET','_POST','_COOKIE') as $_request){ foreach($$_request as $_k => $_v) ${$_k} = _runmagicquotes($_v); } function _runmagicquotes(&$svar){ if(!get_magic_quotes_gpc()){ if( is_array($svar) ){ foreach($svar as $_k => $_v) $svar[$_k] = _runmagicquotes($_v); }else{ $svar = addslashes($svar); } } return $svar; } if(file_exists($insLockfile)){ exit(" 程序已運行安裝,若是你肯定要從新安裝,請先從FTP中刪除 install/install_lock.txt!"); } foreach($$_request as $_k => $_v) ${$_k} = _runmagicquotes($_v);
這裏是一個常常遇到的一個變量覆蓋。算法
致使了咱們能夠覆蓋掉$insLockfile 從而讓file_exists 爲false就不會退出了。致使再次重裝。 這個變量覆蓋不知道咋的 能在一些小cms的安裝文件裏看到。sql
以前看的xdcms 和 frcms 都存在這個變量覆蓋。
這個從早期的phpdisk 的那個 header bypass 到如今的又遇到各類。
好久前的phpdisk的安裝文件中。
判斷是否存在lock文件 若是存在lock文件了 就會header到index.php
可是header 後 他並無exit 因此並不會退出 致使了又是一個重裝。
跟這種相似的還有javascript 彈個框 啥的 也沒exit的。
例子: WooYun: 開源輕論壇StartBBS前臺getshell
例子: WooYun: FengCMS 修復不當致使getshell
這個也比較少, 就隨便說句。 就是像dedecms好久之前的那樣 在安裝完成後會在install.php rename 爲 Install.php.bak 可是因爲apache的解析漏洞 若是沒法識別最後的一個後綴的話 就會向上解析,那麼就又成php了。 而後又結合dedecms安裝時的變量覆蓋 又成重裝了。
這種例子也不算太多, 本身好像也沒遇到過太多。
首先以以前發過的sitestar舉例下
if(file_exists($lockfile) && ($_a=='template' || $_a=='setting' || $_a=='check')) { exit('please delete install.lock!'); }
這裏咱們來理解一下這個邏輯, 這裏的file_exists($lockfile) 由於安裝成功後 lockfile 確定存在的 因此這裏確定會是true 而後再看一下 這裏是一個 && true true 纔會進入語句塊。 那麼若是$_a 不爲 template 、 setting 、 check 的話 那麼後面的就爲false True and false => false就不會進入這個語句塊 就不會exit 再配合後面的
else if($_a=="create"){ $link = mysql_connect($db_host,$db_user,$db_pwd);
恰好有個其餘的 若是$_a 爲 create 那麼就不會退出這個腳本
恰好這個create 能達到Getshell的效果
例子: WooYun: 建站之星Sitestar前臺Getshell一枚
剩下的還有hdwiki以前也有一個基本差很少這樣的例子
if (file_exists(HDWIKI_ROOT.'/data/install.lock') && $step != '8') { echo "<font color='red'>{$lang['tipAlreadyInstall']}</font>"; exit(); }
若是step爲8的話 那麼就不會執行exit了。
case 8: require_once HDWIKI_ROOT.'/config.php'; require_once HDWIKI_ROOT.'/lib/hddb.class.php'; require_once HDWIKI_ROOT.'/lib/util.class.php'; require_once HDWIKI_ROOT.'/lib/string.class.php'; $db = new hddb(DB_HOST, DB_USER, DB_PW, DB_NAME, DB_CHARSET); //install $setting=$db->result_first('select `value` from '.DB_TABLEPRE.'setting WHERE `variable` = \'site_appkey\''); if ($setting){ echo "<span style='font-size:20px;'>百科聯盟開通成功.</span><a href='../'>進入首頁</a>"; break; } //update info $data = $_GET['info']; $data = str_replace(' ', '+', $data); $info = base64_decode($data); if ($info){ $obj = unserialize($info); if(is_array($obj)){ $url2 = 'http://localhost/count2/in.php?action=update&sitedomain='.$_SERVER['SERVER_NAME'].'&info='.$data; $data = util::hfopen($url2); //if gbk then toutf8 if ($lang['commonCharset'] == 'GBK'){ $obj['sitenick'] = string::hiconv($obj['sitenick'], 'gbk', 'utf-8');
恰好這裏step 8 又能執行一些特殊的操做。。 如今就把case 8 註釋掉了。
這裏代碼我就不復制過了 省得佔篇幅。
這裏差很少是我比較常遇到的一些安裝文件常常遇到的問題了,忽然想也想不到其餘啥的了。
這裏再來談一下包含
其實包含也並無什麼好說的。
包含通常也就分爲LFI RFI local file inclusion 和 remote嘛
對於LFI的話 由於不少都限制了包含的後綴結尾必須爲.php Include ($a.'.php') 例如這種的
因此咱們想包含咱們的圖片馬兒的話 那麼就須要截斷後面的這.php
1: 00截斷 須要gpc off && php<5.3.4 2: 長文件名截斷 反正這個我不多成功。 3: 轉換字符集形成的截斷 這個對包含的話基本用不上。上傳的話 就是felixk3y牛發的那個轉換字符集形成的上傳截斷那個。
還有一些cms限制包含的後綴必須爲.php的時候用的是截取字符判斷是否是.php 例以下面一段簡單的代碼
$include_file=$_GET[include_file]; if ( isset( $include_file ) && strtolower( substr( $include_file, -4 ) ) == ".php" ) { require( $include_file ); }
對傳遞過來的截取了後面4個字符 判斷是否是.php 若是是.php才進行包含。
這裏能夠用zip(或者phar)協議嘛(固然這個也是找laterain學的 哈哈)。
首先新建一個1.php 裏面隨便寫個phpinfo把
而後壓縮成.zip 而後把zip的名字改爲 yu.jpg
而後把這個.jpg上傳上去 而後包含
對於一些LFI 找不到上傳圖片的地方的話 也有不少牛發過了一些不能上傳圖片LFI的技巧 各類包含日誌 環境變量啥的 這裏我就也很少說了。
下面再來講RFI
若是能RFI的話 那麼就是最方便的了。
包含遠程文件 或者又是php://input data啥的 各類僞協議。
可是也都知道RFI最大的限制條件就是須要allow_url_include on
且 變量前未定義路徑 或者 常量。
Allow_url_include 默認都是off
那麼不管是allow_url_include on 仍是 變量前無路徑 或者 常量
那都是rfi的硬傷。
這裏介紹一種在allow_url_include off的狀況下也能rfi的
可是成功率也並不過高。
首先在php.ini裏看一下allow_url_include
; Whether to allow include/require to open URLs (like http:// or ftp://) as files. allow_url_include = Off
翻譯一下,容許包含url 例如 http:// ftp:// 之類的協議。
當off的時候確定就是不容許去包含這樣的協議。
這裏咱們先來測試一下
<?php include($_GET[yu]);
首先 allow_url_include && allow_url_fopen 都爲on的時候
成功RFI。
而後 allow_url_include 爲 on allow_url_fopen 爲off
直接包含遠程文件失敗 這時候咱們用一下僞協議試試。
再次成功rfi。
當allow_url_include && allow_url_fopen 爲off的時候。
僞協議失敗。
包含文件
URL file-access is disabled in the server configuration 不容許包含。
確定還有很多人記得好久之前的那個星外無可執行目錄的時候
利用遠程調用cmd繼續提權
那個利用的是共享文件 而後在星外主機上來執行。
那麼這裏咱們也試試
包含共享文件成功。 這裏只本地測試了 沒具體測試。
可是因爲445的緣由 可能基本都失敗。
下面來講一下注入。 這裏談的是mysql。 注入大概也就是把用戶可控的一些變量, 帶入到了數據庫的各類操做當中且沒有作好很好的過濾。 好比註冊用戶的時候檢測用戶名是否存在的時候,把用戶提交的用戶名拿到數據庫中去查詢。 查詢是否存在這個用戶名, 若是這裏對用戶名沒有作好過濾的話 那麼用戶就能夠提交一些特殊字符來注入了。
如今注入的主要緣由是 不少程序員在寫sql語句的時候 仍是搞的語句拼接。
一些用了預編譯或者是在查詢的函數中再來過濾 不少時候就給跪了。
select update insert delete
由於mysql query 並不能執行多行語句, 除非pdo啥的能多行 因此不能像mssql那樣 還能在select後執行個update管理的語句。
對於這四種類型的注入通常的語句的構造也不一樣。
若是有mysql error的話
那麼這四種就都能用報錯注入 這種是比較方便的
若是沒mysql error的話
Select 的注入 通常是用union select 若是把對數據庫中的查詢結果展現出來的話那麼就能直接出數據了。 若是無回顯的話 那麼固然就是盲注了。
Update的注入 若是是在update set的位置的話 那麼咱們能夠找找這個表的哪一個column會被展現出來 例如若是一個update的注入點是在用戶表且是在set位置可控的話 那麼咱們能夠update email這個column 而後去用戶資料看一下本身的email就出數據了 語句例如 update table set email=(select user()) 若是是在where後的話 那麼通常也就是盲注了。
Insert 的注入 也是通常是經過找哪一個column會不會顯示出來 儘可能把要出的數據插入到這個column裏面去。 若是沒顯示的話 也是盲注。
Delete的注入 通常都是盲注了。
數字型注入主要就是由於他的變量並無用單引號引住。
可是基本上都是被強制類型轉換了 intval啥的。
可是有時候會有遺漏的嘛。
而字符型和搜索型的 都是會有單引號引住的。
因此須要閉合單引號再來進行注入。
說到單引號不得不說個php.ini裏的配置
Magic_quotes_gpc 在稍微高點的版本默認都是on
可是卻在應該是5.4就已經廢除了。
從字面意思上來看 就是對GPC QUOTE嘛
GPC 對應的就是GET POST COOKIE
會被轉義的字符爲 ' 「 \ NULL 會在前面添加上一個轉義符。
致使了失去原本的意義 沒法閉合單引號進行注入。
(1) 全局沒有作addslashes的
像這種全局沒有對GET POST COOKIE 作addslashes的 這種廠商基本是會在查詢的時候 再對一些用戶可控的變量進行addslashes 甚至是不進行addslashes 直接帶入查詢的。
這樣的就算在查詢的時候進行addslashes 在不少時候也都能找到幾處遺漏了addslashes的。 這種的比較簡單 很少說。
(2) 全局作addslashes
如今稍微好一點的廠商都知道了在全局文件中對 GET POST COOKIE 作addslashes (甚至是在帶入查詢的函數中再作了轉義或者預編譯 這種給跪) 因此基本不用擔憂哪裏遺漏了哪裏忘記了addslashes) 這種的基本是首先先get magic quotes gpc 判斷gpc是否開啓 若是沒開啓的話 再調用addslashes來轉義 。 若是開啓的話 就不用來addslashes了。 沒開啓就addslashes.
這裏主要講的就是這種類型的注入的一些常見的
這個是一個老生常談的問題, 從一開始的數據庫字符集GBK的寬字節注入 到如今也有好久了。
可是並非字符集爲GBK的就能寬字節注入。
總有一些小夥伴說咋我看的cms 字符集是gbk的 可是咋不能寬字節呢?
這是由於數據庫的鏈接方式不一樣
Set names gbk 這樣的就能寬字節
可是如今這樣的基本都看不到了。 由於基本都是設置了二進制讀取了。
Binary。
這樣的寬字節基本沒了, 卻有了另一種。
由於轉換字符集形成的寬字節注入
從utf8轉到gbk 或者從gbk轉到 utf8啥的。
錦 從UTF8 轉成 GBK以後成了 %e5%5c 74cms對GET POST COOKIE …… 都作了addslashes 因此' 轉義後爲\' ->%5C %e5%5c%5c' 兩個\ 則單引號出來
例子2: WooYun: qibocms 下載系統SQL注入一枚(官網可重現)
由於在全局文件中addslashes
若是咱們能找到一些解碼的 例如urldecode base64_decode的
那麼咱們先提交encode以後的 那麼就能不被轉義了。
而後decode後 再帶入查詢 形成了注入 無視gpc。
這種的很常見。
例子不少 隨便找一個
例子: WooYun: qibocms B2b 注入一枚 //qibocms 注入
例子: WooYun: phpdisk V7 sql注入2 //phpdisk 注入
常見的變量覆蓋 有啥extract 和 parse_str 函數啥的
固然還有$$
變量覆蓋得結合一些具體的場景了。
例如extract($_POST)啥的 直接從POST數組中取出變量
這樣的仍是遇到過幾個 而後覆蓋掉以前的一些變量。
覆蓋的話 通常是覆蓋掉表前綴之類的
Select * from $pre_admin where xxx 像這種的就覆蓋掉$pre
而後直接補全語句而後注入。
例子: WooYun: qibocms分類注入一枚可提高本身爲管理
例子2: WooYun: phpmps 注入一枚
固然 $$ 也挺常常用到的 這個例子很不錯。
例子3: WooYun: MetInfo最新版(5.2.4)一處SQL盲注漏洞
一些cms中 總有一些逗比過濾函數
會把’ 啥的 replace 成空
可是他彷佛忘記了本身全局有轉義?
用戶提交一個' 全局轉義成\' 而後這過濾函數又會把 ' replace 成空
那麼就留下了\ 致使能夠吃掉一個單引號 是double query的話
Select * from c_admin where username=’admin\’ and email=’inject#’
這樣就能夠注入了。
話說以前還遇到過一個廠商。。 以前提交了漏洞 是由於他會把
' " 都會替換成空 而後提交以後 他就去掉了' 就是不把' 替換成空了。
可是他彷佛忘記了 " 也會被轉義。。 那麼提交一個 " 就又剩下了一個轉義符。
例子: WooYun: PHPCMS全版本通殺SQL注入漏洞
固然還有一些replace 是用戶可控的。就是說用戶能夠想把啥提交成空就提交成空
例如好久前的cmseasy 和 ecshop的那個注入
例如這段代碼
$order_sn = str_replace($_GET['subject'],'',$_GET['out_trade_no']);
這裏由於會被轉義 若是提交 ' 就成 \' 這裏能夠看到
這裏清成空的 是咱們get來的 那咱們就想辦法把\ replace掉
可是若是咱們GET提交把\ replace 那麼會被轉義 就是replace掉\
可是咱們只是 \' 因此不能把\去掉 若是我有\ 還要你清空個毛啊。
這裏咱們來理清一下思路。
Addslashes 會對' " \ NULL 轉義
' => \' " => \" \ => \\ NULL => \0
那這裏咱們就提交 %00’ 就會被轉義生成 \0\' 這時候咱們再提交把0替換成空 那麼就成了\' 單引號也就成功出來了。
例子: WooYun: cmseasy繞過補丁SQL注入一枚
由於在不少cms中 基本上都只是對GET POST COOKIE 進行addslashes
而沒有對SERVER進行轉義。
而一些SERVER的變量也是用戶能夠控制的。
例如啥 QUERY_STRING X_FORWARDED_FOR CLIENT_IP HTTP_HOST ACCEPT_LANGUAGE 不少。
這裏最多見的固然也就是X_FORWARDED_FOR
這個通常是在ip函數中用到 若是後面沒有進行驗證ip是否合法的話就直接return 這個大部分時候都會致使注入。
例子1: WooYun: Phpyun注入漏洞二
這裏說到驗證ip 這裏基本都是用的正則來驗證是否合法。
而一些廠商連正則都寫錯。
例如在cmseasy中的驗證ip的正則中(%.+)
致使了後面能夠寫任意字符。
例子2: WooYun: CmsEasy最新版本無限制SQL注射
最近本身在看douphp 裏面的驗證ip的正則本身也發現了一點小問題。
不過也就只是小問題而已。
Douphp中的獲取ip的函數。
function get_ip() { static $ip; if (isset($_SERVER)) { if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) { $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; } else if (isset($_SERVER["HTTP_CLIENT_IP"])) { $ip = $_SERVER["HTTP_CLIENT_IP"]; } else { $ip = $_SERVER["REMOTE_ADDR"]; } } else { if (getenv("HTTP_X_FORWARDED_FOR")) { $ip = getenv("HTTP_X_FORWARDED_FOR"); } else if (getenv("HTTP_CLIENT_IP")) { $ip = getenv("HTTP_CLIENT_IP"); } else { $ip = getenv("REMOTE_ADDR"); } } if (preg_match('/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/', $ip)) { return $ip; } else { return '127.0.0.1'; } } }
來看看驗證ip是否合法的正則
preg_match('/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/', $ip)
這裏咱們仔細來看看 他這裏是準備匹配小數點 可是他直接寫成了.
都知道在正則中.表示的是匹配任意字符 除開換行符意外 可是在開啓/s 修正符之後 換行符也會匹配。
不過他這個.後面沒啥+或者?的 致使也就只能寫一個字符。
他這裏直接寫成了. 那在這裏咱們就能引入單引號了。不過也就一個字符。
這裏的正確寫法應該是.
也差很少 也是由於全局只對COOKIE GET POST 轉義 遺漏了FILES 且不受gpc。
FILES 注入通常是由於上傳 會把上傳的名字帶到insert當中入庫。
而後這裏文件的名字是咱們能夠控制的 因此致使了注入。
而這裏的上傳的名字是咱們能夠控制的。
例子: WooYun: qibocms 黃頁系統SQL注入一枚
還有一些 在入庫的時候纔對文件的名字進行了轉義 而在獲取後綴後 在入庫的時候對文件名轉義了卻沒有對後綴轉義也致使了注入
例子: WooYun: Supesite 前臺注入 #2 (Insert)
好久之前php<4.20的時候 爲了方便 register_globals 默認都是on。
而到了後面 register_globals 的弊端也顯現了出來, 因此也在好久之前默認都是off了。
而到了如今, 不少cms 卻喜歡模仿register_globals 搞起了僞全局機制。
例如啥qibocms metinfo destoon 啥的啊。
這樣是方便了很多, 可是若是哪裏遺漏了初始化 那麼就會致使注入了。
感受這種的挺好玩的 多找了幾個例子。
例子: WooYun: qibocms地方門戶系統注入一個問題(demo測試)
例子: WooYun: qibocms地方門戶系統注入(多處相似,demo測試)
例子: WooYun: 齊博地方門戶系統SQL注入漏洞(無需登陸可批量)
由於在對全局轉義的時候
不少cms 都只是判斷gpc 是否開啓
若是off 就對數組中的value就行addslashes
卻忘記了對數組中的key進行轉義。
那麼這樣也致使了一個問題。 也就是在Gpc off的時候那麼數組的key沒有被過濾 致使能夠引入單引號。(據說低版本的php對二維數組中的key就算gpc on 也不會轉義)
若是哪裏把數組中的key 讀取出來 而後把key帶入到了查詢當中
那麼也會形成安全問題。
並且這樣的例子不少。 簡直慘不忍睹。 例子: WooYun: qibocms V7 整站系統最新版SQL注入一枚 & 另一處能引入轉義符的地方。 //數組key的注入例子: WooYun: qibocms多個系統繞過補丁繼續注入2
例子: WooYun: qibocms所有開源系統 Getshell
例子: WooYun: Discuz 5.x 6.x 7.x 前臺SQL注入漏洞一枚
這種算是比較常見的一種注入的。
代碼大概如
<?php $key=0; $a=$_GET[a][$key]; $b=$_GET[b]; Mysql_query("select * from table where xxx='$a' and xx='$b'")
若是這裏$_GET[a] 提交的是一個數組 且含有一個key爲0的那麼$a就是對應的這個key的value
可是這裏並無強制要求爲數組。
那麼咱們提交一個字符串 那麼後面的[0] 那麼就是截取的第一個字符
在全局中 單引號被轉義爲\' 截取第一個字符就爲了\
吃掉一個單引號 而後就在$b處寫入inject能夠注入了。
例子: WooYun: qibocms 地方門戶系統 注入#4(demo測試)
還有map發的那Disucz 7.2的那注入也同樣。
很常見的一種洞。
比較常見的uc 和 alipay tenpay chinabank 啥的
特別是uc 由於默認uc裏面都會striplashes
Uc的話 通常會遇到的問題是uckey默認的。
或者是uckey這個常量根本就沒有初始化。
致使了uckey可控 再致使了Getshell 或者 注入啥的。
還有tenpay 和 alipay 啥的 一些是由於忘記把過濾的文件包含進來
且key默認是空的 致使能夠經過驗證。
例子: WooYun: phpmps 注入 (可修改其餘用戶密碼,官網成功) // phpmps uc致注入
例子: WooYun: PHPEMS (在線考試系統) 設計缺陷 Getshell一枚(官網已shell) /phpems uc致getshell
例子: WooYun: 最土團購注入一枚可直接提高本身爲管理 & 無限刷錢。 //最土團購 chinabank致注入
例子: WooYun: Destoon Sql注入漏洞2(有條件) //destoon tenpay致注入
例子: WooYun: CSDJCMS程式舞曲最新版Sql 一枚 //csdj tenpay致注入
其實也不僅是數字型 只是說一些忘記加單引號的地方都這樣。
只是通常數字型的都不會加單引號的。
通常的是
$id=$_GET[id]; Select * from table where id=$id;
$id 沒被單引號 且 沒有被強制類型轉換 那麼就算addslashes了 因爲不須要去閉合單引號 因此也無影響。
例子: WooYun: qibocms 地方門戶系統 注入#3 (demo測試)
並非一些數字型 一些其餘的點也有些忘記加單引號 致使了注入。 例子: WooYun: Supesite 前臺注入 #3 (Delete)
這裏supesite的注入還涉及到了一個設計缺陷。 這裏把
$query = $_SGLOBAL['db']->query('SELECT * FROM '.tname('spacetags').' WHERE itemid=\''.$itemid.'\' AND status=\''.$status.'\'')
$itemid 首先帶入到了查詢當中 是被單引號了的。。 若是查詢出來的有結果 纔會帶入到delete中 若是無結果 就不執行delete的語句了。 而在數據庫中itemid中 存儲的是int類型 因此他這裏本意是想要用戶只能提交數字型才能查詢出結果。 若是不是提交的數字的話 那麼就查詢不出來結果 就不去執行下面的delete語句了。 可是因爲mysql的類型轉換 由於他這裏儲存的是int類型 因此咱們提交4xxxxx 跟咱們提交4 是同樣的
$_SGLOBAL['db']->query('DELETE FROM '.tname('spacetags').' WHERE itemid='.$itemid.' AND tagid IN ('.simplode($deletetagidarr).') AND status=\''.$status.'\'');
而後就執行這個delete語句 而後沒單引號 形成了注入。
例子: WooYun: phpyun v3.2 (20141226) 兩處注入。
這個phpyun的注入 主要是由於php是弱類型語言
一些廠商喜歡這樣寫
If ($a>1){ Mysql_query(select id from table where id=$a) }
他這個原本是想用戶提交數字才能經過這個判斷 可是因爲弱語言 1+asd啥的 都能經過 因此又致使了注入。
也是一種比較常見的注入。 涉及到的是入庫和出庫。 由於有全局轉義 而後入庫的時候
Insert into table (username) values ('a\'');
這樣入庫後 轉義符就會消失 那麼就是a' 若是哪裏再把這個查詢出來 那麼也就是出庫的是a' 若是再把出庫的 再帶入到了查詢啥的 那麼就再次成功的引入了單引號致使了注入
例子: WooYun: phpyun v3.2 (20141226) 兩處注入。 例子: WooYun: qibocms 地方門戶系統 二次注入#5(demo測試) 例子: WooYun: 74cms (20140709) 二枚二次注入 例子: WooYun: Hdwiki最新版二次注入一枚
比較是硬傷的是 不少時候數據庫中存儲的長度是有限制的。 因此一些也不是太好利用。
不知道也應不該該把這個歸爲一類。
大概是由於一些查詢的時候 直接把$_POST啥的 直接帶入到了查詢函數當中
例如cmseasy的rec_insert的查詢函數中。
而後foreach key 出來 而後foreach 出來的key 作了查詢中的column
這種的防止方法通常是 把數據庫中的column查詢出來 而後in_array 判斷一下$_POST出來的key 是否在數據庫中的column中 下面兩個例子就是這樣修復的。
例子: WooYun: 雲人才系統SQL注入,繞過WAF 例子: WooYun: Cmseasy SQL注射漏洞之三
有些cms 在全局addslashes後 而後在後面的文件中又stripslashes
去掉了轉義符 而後又能夠閉合單引號了。
$_SESSION['flow_consignee'] = stripslashes_deep($consignee);
例子: http://www.2cto.com/Article/201301/182509.html //以前的ecshop注入 。
有些cms 有的時候會限制用戶輸入的長度
因此只截取一部分
例如uchome的cutstr($asd,32);
這樣只容許輸入32個字符 並且uchome裏面的這個也沒有像dz那樣截取字符的後面加...
那麼若是咱們提交一個1111111111111111111111111111111’
被轉義後成1111111111111111111111111111111\’
而後截取32個字符 就是1111111111111111111111111111111\
若是又是double query的話 吃掉一個單引號 而後下一個連着的可控變量又能夠注入了。
結果在uchome中找到了個能引入轉義符的 結果只有一個可控的。
例子: WooYun: Hdwiki (20141205) 存在7處SQL注入漏洞(含以前處理不當安全的漏洞) //裏面的0x06
不知道放哪。這個也放到注入板塊來把。。
其實就是此次的DZ6.X 7.X 那個任意代碼執行的漏洞
if (isset($_REQUEST['GLOBALS']) OR isset($_FILES['GLOBALS'])) { exit('Request tainting attempted.'); } foreach(array('_COOKIE', '_POST', '_GET') as $_request) { foreach($$_request as $_key => $_value) { $_key{0} != '_' && $$_key = daddslashes($_value); } }
主要關鍵代碼就上面這兩段。 這裏把GET POST COOKIE 循環出來 而後註冊一個變量 可是 這裏不容許建立GLOBALS變量 而後DZ7.X 就是用這樣處理的 若是設置了REQUEST 的 GLOBALS
就直接退出
這段代碼在好久之前確實是沒什麼問題
由於那時候的request order 仍是gpc
可是在php 5.3 之後 request order 默認成了gp
也就是成了get 和 Post 不包含cookie了。
因此 $_REQUEST裏面就不包含COOKIE提交來的了。
並且這後面也把COOKIE循環出來 註冊變量
因此這裏咱們在COOKIE裏面提交GLOBALS 就不會被檢測出來了。
並且也成功註冊了GLOBALS變量。
因此在結合後面的一些些代碼就形成了代碼執行。
例子: WooYun: Discuz!某兩個版本前臺產品命令執行(無需登陸)
以上就差很少是我常常所遇到的注入問題 好像暫時也想不到其餘什麼的了
下面介紹一些我在cms遇到的找回密碼時候犯得錯誤。
找回密碼不少都是驗證的token 就是在找回密碼的時候生成一個token 而後存儲到數據庫中。 而後把找回密碼的地址發到郵箱中 url中就含有token 由用戶點開後就能修改密碼 基本就是驗證的這個token。 其實通常的能夠找回任意用戶密碼的緣由就是弱token 致使能夠被攻擊者搞到。 包括不少廠商驗證的時候就是四位純數字啥的。 能夠枚舉。 固然也能夠延伸一下, 一些cms的密碼加密方式很難破掉。 有時候咱們拿到了管理的密碼破不掉也是雞肋。 因此有時候也能夠利用這種方法 通常找回密碼是用的郵箱 首先咱們能夠注入把管理的郵箱注入出來 而後再去找回密碼 再把數據庫的token注入出來 再構造一下地址 就能重置密碼。 這個給我印象比較深的是 在ssctf的比賽中嘛 當時機油問了問我 那wordpress那題 有個插件的注入 而後由於都知道wp的加密基本很難破。 因此也是用的這種方法。 由於通常都是弱token的問題 隨便找幾個例子了
$resetpwd = md5(rand());
能夠看到這個生成的token 就是對rand()函數生成出來的數字進行md5一次
來看一下rand()
註釋:在某些平臺下(例如 Windows)RAND_MAX 只有 32768。若是須要的範圍大於 32768,那麼指定 min 和 max 參數就能夠生成大於 RAND_MAX 的數了,或者考慮用 mt_rand() 來替代它。 若是不指定一些參數的話 那麼最大值才32768 一個並不算大的值 那麼咱們首先對這32768種可能 md5出來一個列表 而後咱們直接枚舉這32768種可能 總會有一個對的。
例子: WooYun: Thinksaas找回密碼處設計錯誤利用帳戶可找回密碼。
$encryptstring=md5($this->time.$verification.$auth);
補丁後 多了一個$auth $timetemp=date("Y-m-d H:i:s",$this->time); $auth = util::strcode($timetemp, 'ENCODE'); 能夠$auch 是對時間來了一個算法。 結果這個算法的KEY並無初始化 致使了若是咱們知道了這個時間 就能夠本身生成出來加密的字符串 這裏帶入算法的是時間 這裏是咱們能夠知道的。
例子: WooYun: Hdwiki設計缺陷知郵箱可改密碼(包括管理員) //繞過補丁繼續找回hdwiki任意用戶密碼
這個上傳就大概說說。
通常的上傳漏洞多是未驗證上傳後綴 或者是驗證上傳後綴被bypass 或者是上傳的文件驗證了上傳後綴可是文件名不重命名。
對於那些驗證了後綴可是文件名不重命名的
通常能夠試試截斷yu.php%00.jpg 固然%00 要urldecode
固然 畢竟截斷雞肋了。 上面提到過限制條件了。
還能夠是結合各類webserver的解析漏洞
例如iis6的 xx.asp/yu.jpg yu.php;.jpg yu.asp;.jpg aspx 固然不能這樣解析了。
若是不重命名的就上傳這樣就好了。
Nginx的低版本解析漏洞: yu.jpg/1.php 對於這種直接上傳一個xxxx.jpg 再在這後面加上各類/.php 試試的
Apache解析漏洞 yu.php.xxx 在最後一個後綴識別不出來的時候 那麼就向上解析
最終解析成.php
像phpweb後臺那個上傳漏洞。不少人遇到apache的時候
沒法截斷的時候就上傳一個yu.php.jpg 有些人比較疑問的是爲啥有時候成功有時候失敗。
這個主要是看os 像windows的話 .jpg 就直接是圖片了
因此在windows下 就直接識別成圖片了 而不是.php
而在linux下 .jpg不被識別 就向上識別成.php
這些解析漏洞在上傳中也挺常常遇到的。
上傳的驗證通常是 MIME、客戶端的JS驗證、白名單、黑名單。
前面兩種都比較簡單。
白名單就是容許用戶上傳哪些後綴的。 黑名單就是禁止用戶上傳哪些後綴的。
這兩種相比來講通常是黑名單容易bypass一點。 黑名單的繞過仍是得具體看他黑名單的代碼。 有的直接大小寫就過。 有些沒對文件名trim的 直接在文件名後面加空格。 Windows下的 文件名後%81-%99 decode後的 或者是windows下的特性 .php::$data 這樣上傳上去依舊是.php
其實上傳還挺重要的。。 可是我又不知道說哪些。 仍是具體看代碼把。
這個主要是涉及到的是 任意文件刪除 任意文件複製 任意文件重命名 任意文件移動 任意文件下載……。 由於像如今的cms不少都自帶得有加密 解密 函數 例如qibocms的mymd5 Dz的authcode 啥的。 對於這些任意文件操做的 首先能夠試試拿到配置文件中的數據庫的鏈接賬號和密碼 嘗試外聯一下 可是不少時候都是隻容許本地連的 不少時候很差利用的時候能夠利用拿到配置文件 而後拿到這些函數的key 而後本身生成一個加密的字符串 而後再結合具體的代碼進行最大化的利用。
通常是挺很差利用的,仍是結合具體的場景,有些由於全局的過濾而不能注入的,能夠嘗試用任意文件刪除,刪掉這個文件,再進行注入 通常的利用仍是經過刪除安裝文件生成的lock文件,而後達到重裝。
不過這樣弊很大。
例子: WooYun: phpyun (20141230) 任意文件刪除致注入可改任意用戶密碼(4處打包)
複製的話 確定涉及到了 要複製的文件 要複製到的路徑。
若是是要複製的文件可控 要複製到的路徑不可控的話 例如qibocms以前的一個洞
copy(ROOT_PATH."$webdb[updir]/$value",ROOT_PATH."$webdb[updir]/{$value}.jpg");
這裏$value 是可控的 可是又不能截斷 複製到的路徑限制了.jpg結尾。
這時候咱們就能夠把$value控制爲 保存了qibocms的加密函數的key的配置文件
而後複製後 成了一個.jpg 那咱們就能夠直接打開 看到key了
例子: WooYun: Qibocms圖片系統任意文件查看致使的多處注入(可提高本身爲管理員)
若是兩個都徹底可控的話 那確定是直接把本身的圖片複製成一個.php馬兒了。
其實跟上面複製差很少, 不少時候也是經過下載配置文件 拿到key。 再進行各類操做。。
例子: WooYun: qibocmsV7整站系統任意文件下載致使無限制注入多處(可提高本身爲管理 Demo演示)
這個例子還涉及到了一個win的特性bypass 黑名單
這種問題主要是想進各類辦法把這些加密函數的key拿到 或者想辦法加密一些特殊字符而後拿到加密的字符串
加密函數確定就涉及到了各類算法。
算法問題通常主要是由於一些弱算法 致使了 知道明文 知道密文 可逆
拿到加密函數中的key 從而再本身生成一個本身想要的加密字符串。
再結合具體的點 而後進行具體的利用。
例子: WooYun: DedeCMS-V5.7-SP1(2014-07-25)sql注入+新繞過思路 例子: WooYun: phpcms最新版繞過全局防護暴力注入(官網演示)
還有的一類算是 一個點 要加密的是咱們可控的 並且密文會輸出 並且這個可控的點能引入特殊字符 那麼咱們就把一些特殊字符帶入到這裏面 而後拿到密文 再找到一處decode後會進行特殊操做的點 而後進行各類操做。
例子: WooYun: 程氏舞曲CMS某泄露,致使sql注入
例子: WooYun: PHPCMS最新版(V9)SQL注入一枚
例子: WooYun: 一個PHPWIND可拿shell的高危漏洞
例子: WooYun: PHPCMS V9 一個隨心所欲的漏洞
寥寥草草的把這篇文章寫完了。
比本身預期想的少寫了不少, 由於在一開始寫的時候仍是挺有感受的。
由於讀書一個月也才放一次假, 都是抽時間在慢慢寫着。
後面差很少寫了1W字的時候,存稿居然丟了, 弄了半天也沒找回
就感受不想寫了, 後面又翻了翻 找到了一篇本身以前保存的寫了差很少兩三千字的
而後就再慢慢的開始寫了, 也就草草的結束了。
固然這裏只是總結了一些常見的類型, 確定在實戰中會遇到各類各樣的狀況 各類過濾啥的。
各類邏輯錯誤須要本身慢慢去體會了。