POST注入
POST注入与显错注入的区别就在于传参方式的不同,后者是GET传参可以显示在URL栏里
GET和POST :他们其实没啥区别
1、GET会显示在URL栏里面
2、GET会进行一次URL编码
3、POST能够传输更多的数据
POST注入高危点:
登录框
查询框
等各种和数据库有交互的框
我们直接上练习题:
前闭合后注释,猜字段数,查库表字段及数据
老样子到4报错了,所以是3个字段。
查表查到了flag,我们接着进去查字段
接着查flag这个字段里的数据
提交!
Rank2
不出意外还是三个字段。
老流程走一遍
估摸着第二题提交第二个flag。
Head注入
PHP 全局变量 - 超全局变量
PHP 中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可用。
这些超全局变量是:
$_REQUEST (获取GET/POST/COOKIE) COOKIE在新版本已经无法获取了
$_POST (获取POST传参)
$_GET (获取GET的传参)
$_COOKIE (获取COOKIE的值)
$_SERVER (包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组)
$_SERVER[‘HTTP_HOST’] 请求头信息中的Host内容,获取当前域名。
$_SERVER[“HTTP_USER_AGENT”] 获取用户相关信息,包括用户浏览器、操作系统等信息。
$_SERVER[“REMOTE_ADDR”] 浏览网页的用户ip。
updatexml() 更新xml文档的函数
语法:updatexml(目标xml内容,xml文档路径,更新的内容)
updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)
这里是去更新了XML文档,但是我们在XML文档路径的位置里面写入了子查询,我们输入特殊字符,然后就因为不符合输入规则然后报错了
注意:updatexml()一般配合and或者or使用,一般用or比较好,而且和联合查询不同的是它不需要在乎字段数
Rank1
这题我们先来看一波源码:
特定符号被禁止了一般POST注入不行,可以通过绕过去做但是不在今天学的内容里面就不过多阐述,这里我们看到像uagent头传两个数据就行了,在谷歌浏览器可以使用Profile这个插件来改,火狐可以使用hackbar来改,或者正确登陆时burp抓包来改,我喜欢通过抓包的方式来改。
先抓包,把我们的语句放到User-agent里面,然后放包就行了
继续到flag_head里面去找答案就行了,老样子抓包,改ua然后在放包
在进flag_h1进行老操作
出来了!应该是第1个,我们提交。
Rank2
看波源码,发现这里要改的就不是ua了而是refer
报错注入查库,表,字段和数据
第二题那我们就提交第二个答案呗
Rank3
调用了getip()函数,尝试各种方法去获取你的IP如果以上方法都不行,它会到最后一步remote_addr来提取你的TCP连接的IP,如果用了代理,那么它获取的就是你的代理的IP。
代理: 让A帮自己去访问某个网站(我们不跟真实的网站发生关系,通常通过代理去完成)
高匿代理 => 匿名的,别人并不知道你的原始IP
透明代理 => 别人知道你的IP是啥
接下来我们只需要往burp的重发器里面写入一下东西放包就行了
X-Forwarded-For : Header头里面的东西
老样子我们交第三个答案。
哎?答案咋错了,不应该呀,其实答案就是错了!为什么?
因为我偷懒用了group_concat来直接输出所有查询结果
这里注意:报错注入可能会限制了输出的字符串长度,所以最好老老实实用limit来一条一条输出,我是因为这个靶场输出的查询结果不多所以还是偷懒用group_concat没想到最后设置了个陷井!
显然是第三条flag受到限制没有输出完,我们在提交看看
盲注
显错注入(页面有回显的注入)
报错注入属于(页面上也是有内容显示)
1.布尔型盲注
页面还能告诉你,是否有数据查询
length()函数返回字符串的长度
substr()截取字符串(语法:SUBSTR(str,pos,len); --substr(截取什么,从哪里截,截多少)
ascii()返回字符的ascii码[将字符变为数字wei]
sleep()将程序挂起一段时间n为n秒
if(expr1,expr2,expr3)判断语句如果第一个语句正确就执行第二个语句如果错误执行第三个语句
if(条件,满足的时候执行什么,不满足的时候执行什么)
在这里我们要忘掉union联合查询,因为页面没有输出点,所以order by也没有意义了
首先我们还是查库:
利用length()函数我们先判断库的字符串长度
说明库的字符串长度等于12
现在我不光要知道它字符串长度,我还要知道它是什么叫啥名怎么做?
利用substr()函数截取:
但是一个个的截取工作量有点大现在是12个字符,那万一以后出现更大的字符串长度还要一个个的截取人不得疯了…
这里我们可以在substr的外面在套一个ascii()函数,通过判断ascii码值来确定所对应的字符,这样的话我们可以利用burp来不断发送数据包,再进行批量替换。
先抓个包
右键将它发送到这里
选中107进行替换
在payload type里面选择number跑数字,在底下设置里面调从1开始跑到127,一次跑一位,然后跑包
跑包完成,我们去看length,我们发现它基本都是在3164和3165之间晃悠
但是在这里我们看到了3197很与众不同呀,发现它对应替换的ascii是107和我们用ascii函数一次次试出来的结果一样
但是呢,这里我们也只是跑了库的字符串的第一个字符,接下来我们要跑整个字符串!
我们要将类型替换成最下面那个才能进行多个替换
我们选中这两个进行替换
库有12个字符我们将payload1设置成1到13,payload2还是1到127
先框中的是1,后框的是2,然后开始跑
跑完了,看看这个一共1651条数据,拿手工替换绝对会绝望的!
一目了然107,97,110,119,111,108,111,110,103,120,105,97在对应ascii码表翻译一下就行
把那我们看看常规做法
猜解当前数据库名称长度:
id=1’ and (length(database()))>9#
利用ASCII码猜解当前数据库名称:
and (ascii(substr(database(),1,1)))=115–+返回正常,说明数据库名称第一位是sand (ascii(substr(database().2,1)))=101–+返回正常,说明数据库名称第二位是e猜表名:
and (asci(substr((select table_name from information_schema.tables where table_schema=database(limit 0,1),1,1)))=101–+返回正常,说明数据库表名的第一个的第一位是e
猜字段名
and (asci(substr((select column_name from information_schema.columns where table_name='zkaq’limit 0,1),1,1)))=102–+返回正常,说明zkaq表中的列名称第一位是f
猜内容
and (ascii(substr(( select zKaQ from zkaq limit 4,1),1,1)))=122–+返回正常,说明zKaQ列第一位是z
不得不说是真滴麻烦,所以使用burp可以大幅节省时间
另外两题的布尔盲注一样的操作手法
2.时间型盲注
页面无论怎么搞,我都不变
我们利用sleep()和if(expr1,expr2,expr3)这两个函数:
例如 if(length(database())>110,sleep(6),1)来进行判断库名字符串长度,然后在嵌套另外几个函数并利用burp拿到库名
这里的盲注通过burp跑ascii码来拿到字段里的数据效率有些低,所以这里我们拿到库名之后就直接拿sqlmap来跑吧
五一假期回来补的文章多少有些赶,就不再一一演示了!
未完待续…