The centre-back's existing deal was due to expire at the end of the upcoming season.
Morrison, 26, joined the Bluebirds from Reading in 2014, having previously played for Swindon and Huddersfield.
He has made 120 appearances and scored 13 goals for Cardiff, who rejected a bid for him from fellow Championship side Sheffield Wednesday in June.
Cardiff City captain Sean Morrison has signed a new contract which will keep him at the club until 2020.