WEB服务端安全---注入攻击

注入攻击是web领域最为常见的攻击方式,其本质是把用户输入的数据当作代码执行,主要缘由是违背了数据与代码分离原则,其发生的两个条件:用户能够控制数据输入;代码拼接了用户输入的数据,把数据当作代码执行了。php

下面是几种常见注入攻击及其防护方法:前端

SQL注入及常见攻击技巧

经典注入  如:

$username = $_POST['username'];
$sql = "select * from usertable where username="."'".$username."'"

正常状况下用户输入 ‘Tom’ ,sql为mysql

"select * from usertable where username='Tom'";

但若是用户输入 ”Tom' ; drop table usertable--“,sql以下:web

"select * from usertable where username='Tom';drop table usertable--";

若是咱们的服务端代码,数据库权限没作任何处理,那么结果伤不起。sql

而且当用户输入了能够致使拼接后sql有语法错的时候,若是服务器开启了错误显示,那么将会是攻击更加便利容易,由于错误信息可能会暴露咱们的数据库信息或者sql语句的雏形等等。shell

 

 

盲注:

大多数状况下服务器是关闭错误回显的,没有提示的状况下,攻击者又总结出了盲注:sql注入过程当中,sql语句执行的选择后,选择的数据不能回显到前端页面。此时,攻击者须要利用一些方法进行判断或者尝试,这个过程称之为盲注。数据库

攻击者经过真假命题的拼接根据页面返回状况判断sql漏洞是否存在。安全

好比:http://news.com/newsIndo.php?id=1,执行的sql为 select * from newstable where id =1;服务器

攻击者先是http://news.com/newsIndo.php?id=1 and 1=2  而后  http://news.com/newsIndo.php?id=1 and 1=1 app

and 1=2 时 一般是空页面 或者错误信息,若是 and 1=1的时候页面正常返回,就说明,and语句成立,也就说明sql漏洞存在,攻击者不知道会拼接什么样的坏心思...

盲注高级技巧Timing Attack 利用数据库自身函数的的执行形成的返回变化来判断漏洞是否存在,好比 MySQL BENCHMARK()函数。

 

数据库攻击机巧

常见Payload

SQL注入能够猜解出数据库的对应版本,好比下面这段Payload,若是MySQL的版本是4,则会返回true。

http://www.site.com/news.php?id=5 and substring(@@version,1,1)=4

下面这段Payload,则是利用union select来分别确认表名admin是否存在,列名passwd是否存在:

id=5 union all select 1,2,3 from admin

id=5 union all select 1,2,passwd from admin

进一步,想要猜解出username和password具体的值,能够经过判断字符的范围,一步步读出来。

id=5 and ascii(substring((select concat(username,0x3a,passwd) from users limit 0,1),1,1))>64

这个过程很是的繁琐,因此很是有必要使用一个自动化工具来帮助完成整个过程。

sqlmap.py就是一个很是好的自动化注入工具。

在注入攻击的过程当中,经常会用到一些读写文件的技巧。好比在MySQL中,就能够经过LOAD_FILE()读取系统文件,并经过INTO  DUMPFILE写入本地文件。固然这要求当前数据库用户有读写系统相应文件或目录的权限。

命令执行

在MySQL中,除了能够经过导出webshell间接地执行命令外,还能够利用“用户自定义函数”的技巧,即UDF(user-defined functions)来执行命令。

攻击存储过程

一些存储过程也是对攻击过程有帮助的,好比:SQL Server 中的xp_cmdshell,注入时能够利用其执行系统命令。存储过程本省也可能给存在注入漏洞。

编码问题

有时候不一样的字符编码也可能致使注入漏洞的出现,好比 转义符 ‘\’ 可能会由于字符编码的不一样被省略掉,保证数据库,操做系统,web应用的字符编码统一能够避免此类问题。

 

防护SQL注入

使用预编译语句

通常来讲,防护sql注入的最佳方式就是使用预编译语句,绑定变量。使用预编译的sql语句,语句的语义不会发生改变。在sql中变量用?表示,攻击者没法改变sql的结构,好比下面PHP绑定变量,使用预编译语句的示例:

1 $sql = "insert into usertable (username,password,phone) value(?,?,?)";
2 $stmt = $mysqli->prepare($sql); 3 $stmt = bind_parm("sss",$username,$password,$phone); 4 $username = 'Tom'; 5 $password = md5('123456'); 6 $phone = '13510345678'; 7 $stmt->execute();

此时就算攻击者插入相似于 Tom’ or ''='1的字符串,也只会将其当作username来插入,不会改变语句的执行。

检查数据类型

对输入数据的数据类型进行检查,能够很大程度上对抗sql注入,好比整形integer,亦或是邮箱,时间日期等特定格式数据。

使用安全函数

使用足够安全的编码函数,好比:ESAPI.encoder().encodeForSQL( new OracleCodec(), queryparam );

Codec ORACLE_CODEC = new OracleCodec();
String query = "SELECT user_id FROM user_data WHERE user_name = '" + ESAPI.encoder().encodeForSQL( ORACLE_CODEC , req.getParameter("userID")) + "' and  user_password = '" +  ESAPI.encoder().encodeForSQL( ORACLE_CODE , req.getParameter("pwd")) +"'";

最小权限及关闭错误回显

关闭服务器错误回显,避免数据库信息的暴露,数据库使用最小权限原则,避免root等高级帐号在web应用中的直接使用,数据库帐号不该该有建立自定义函数,操做本地文件等权限。

 

 

XML注入

$doc = new DOMDocument('1.0','utf-8');
$doc -> formatOutput = true; $user = $doc -> createElement('user'); $username = $doc -> createElement('username'); $namevalue = $doc -> createTextNode($_POST['username']); $username -> appendChild($namevalue);//将标签内容赋给标签 $user -> appendChild($username); $doc -> appendChild($user); $doc -> save("user.xml");

正常状况下用户输入 Tom将保存下面xml文件

<?xml version="1.0" encoding="utf-8"?>
<user>
    <username>Tom</username>
</user>

可是若是用户输入恶意数据

Tom</username></user><user><username>Jack</username></user>

此时xml文件

<?xml version="1.0" encoding="utf-8"?>
<user>
    <username>Tom</username>
</user>
<user>
    <username>Jack</username>
</user>

这就是XML注入。XML注入,能够对用户输入数据中的包含”语言自己的保留字符“行进转义便可。

 

代码注入

代码注入与命令注入都是由一些不安全函数或方法引发的如:eval()

$var = 'varname';
$k = $_GET['tag']; eval("/$var = $k;");

攻击者能够经过下面Payload实施代码注入:

/indexPHP?tag=1;phpinfo()

又好比 system()这个函数,能够经过代码注入致使命令注入

$error =system('cat '.$_GET['page_id'],$return_var);
echo $error;

攻击者经过 index.php?page_id=loquesea;ls利用system函数执行本身想要的系统命令。

 

防护对抗代码注入,命令注入,须要禁用一些像eval(),system()等能够执行系统命令的函数,非要用到就须要对用户输入的数据作处理,此外PHP中动态include远程文件,也是能避免就避免。

 

CRLF(\r\n)注入

CRLF实际上是两个字符\n\r,经常被用做语义之间的分隔符,所以CRLF注入极可能改变原有的语义,以下

$log = fopen("login.log", "w");
$txt = "user login failed for: \n"; fwrite($log, $txt); fclose($log);

正常状况会记录以下在login.log日志文件中,

user login failed for :user1
user login failed for :user2

可是由于没有对换行 \n作处理,当攻击者输入 user2\nuser2 login succeeded for :user2 

日志中结果就会变为

user login failed for :user1
user login failed for :user2 user login succeeded for :user2

多了一条伪记录,user2并无登陆成功。

CRLF注入不只仅能够log注入,凡是利用CRLF做为分隔符的地方均可能存在这样的注入,像是”注入HTTP头“等。

对抗CRLF注入其实只须要处理好 \r \n这两个保留字符便可。

 

写在最后:注入攻击主要是违背了数据与代码分离原则致使的,其先决条件是用户能控制数据输入,而且代码拼接了用户输入的数据,把数据也打个代码执行了。因此,防护听从数据域代码分离原则,在拼接的地方作好安全检查和处理就能避免此类问题了。

相关文章
相关标签/搜索